From 626fb02e928f9a39c50657666d37113a3ff47567 Mon Sep 17 00:00:00 2001 From: Ashish Yadav <48384865+criticalAY@users.noreply.github.com> Date: Mon, 20 May 2024 16:07:17 +0530 Subject: [PATCH 001/138] fix: use field check from backend and display error accordingly * UnitTest: NoteEditorTest updated to check for error message Co-authored-by: David Allison <62114487+david-allison@users.noreply.github.com> --- .../main/java/com/ichi2/anki/NoteEditor.kt | 87 ++++++++++--------- .../com/ichi2/anki/NoteFieldsCheckResult.kt | 77 ++++++++++++++++ AnkiDroid/src/main/res/values/02-strings.xml | 2 - .../java/com/ichi2/anki/NoteEditorTest.kt | 32 ++++--- 4 files changed, 143 insertions(+), 55 deletions(-) create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/NoteFieldsCheckResult.kt diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt b/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt index 09efe96479d1..4c75aa500767 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt @@ -53,6 +53,7 @@ import androidx.core.content.edit import androidx.core.content.res.ResourcesCompat import androidx.core.text.HtmlCompat import androidx.core.view.isVisible +import androidx.lifecycle.lifecycleScope import anki.config.ConfigKey import anki.notes.NoteFieldsCheckResponse import com.google.android.material.color.MaterialColors @@ -106,6 +107,7 @@ import com.ichi2.libanki.utils.TimeManager import com.ichi2.utils.* import com.ichi2.utils.IntentUtil.resolveMimeType import com.ichi2.widget.WidgetStatus +import kotlinx.coroutines.launch import org.json.JSONArray import org.json.JSONObject import timber.log.Timber @@ -316,31 +318,31 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags SAME_NUMBER, INCREMENT_NUMBER } + private var addNoteErrorMessage: String? = null + private fun displayErrorSavingNote() { - val errorMessageId = addNoteErrorResource - showSnackbar(resources.getString(errorMessageId)) + val errorMessage = snackbarErrorText + // Anki allows to proceed in case we try to add non cloze text in cloze field with warning, + // this snackbar helps replicate similar behaviour + if (errorMessage == TR.addingYouHaveAClozeDeletionNote()) { + showSnackbar(errorMessage, Snackbar.LENGTH_INDEFINITE) { + setAction(R.string.dialog_ok) { + lifecycleScope.launch { + saveNoteWithProgress() + } + } + } + } else { + showSnackbar(errorMessage) + } } - // COULD_BE_BETTER: We currently don't perform edits inside this class (wat), so we only handle adds. - // Otherwise, display "no cards created". - @get:StringRes @VisibleForTesting - internal val addNoteErrorResource: Int - get() { - // COULD_BE_BETTER: We currently don't perform edits inside this class (wat), so we only handle adds. - if (isClozeType) { - return R.string.note_editor_no_cloze_delations - } - if (getCurrentFieldText(0).isEmpty()) { - return R.string.note_editor_no_first_field - } - return if (allFieldsHaveContent()) { - R.string.note_editor_no_cards_created_all_fields - } else { - R.string.note_editor_no_cards_created - } - - // Otherwise, display "no cards created". + val snackbarErrorText: String + get() = when { + addNoteErrorMessage != null -> addNoteErrorMessage!! + allFieldsHaveContent() -> resources.getString(R.string.note_editor_no_cards_created_all_fields) + else -> resources.getString(R.string.note_editor_no_cards_created) } override val baseSnackbarBuilder: SnackbarBuilder = { @@ -962,6 +964,7 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags sourceText = null refreshNoteData(FieldChangeType.refreshWithStickyFields(shouldReplaceNewlines())) showSnackbar(TR.addingAdded(), Snackbar.LENGTH_SHORT) + addNoteErrorMessage = null if (caller == CALLER_NOTEEDITOR || aedictIntent) { closeEditorAfterSave = true @@ -981,6 +984,20 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags } } + private suspend fun saveNoteWithProgress() { + // adding current note to collection + withProgress(resources.getString(R.string.saving_facts)) { + undoableOp { + editorNote!!.notetype.put("tags", tags) + notetypes.save(editorNote!!.notetype) + addNote(editorNote!!, deckId) + } + } + // update UI based on the result, noOfAddedCards + onNoteAdded() + updateFieldsFromStickyText() + } + @VisibleForTesting @NeedsTest("14664: 'first field must not be empty' no longer applies after saving the note") @KotlinCleanup("fix !! on oldModel/newModel") @@ -993,17 +1010,6 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags // treat add new note and edit existing note independently if (addNote) { - // Different from libAnki, block if there are no cloze deletions. - // DEFECT: This does not block addition if cloze transpositions are in non-cloze fields. - if (isClozeType && !hasClozeDeletions()) { - displayErrorSavingNote() - return - } - if (getCurrentFieldText(0).isEmpty()) { - displayErrorSavingNote() - return - } - // load all of the fields into the note for (f in editFields!!) { updateField(f) @@ -1019,17 +1025,16 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags } reloadRequired = true - // adding current note to collection - withProgress(resources.getString(R.string.saving_facts)) { - undoableOp { - editorNote!!.notetype.put("tags", tags) - notetypes.save(editorNote!!.notetype) - addNote(editorNote!!, deckId) + + lifecycleScope.launch { + val noteFieldsCheck = checkNoteFieldsResponse(editorNote!!) + if (noteFieldsCheck is NoteFieldsCheckResult.Failure) { + addNoteErrorMessage = noteFieldsCheck.getLocalizedMessage(this@NoteEditor) + displayErrorSavingNote() + return@launch } + saveNoteWithProgress() } - // update UI based on the result, noOfAddedCards - onNoteAdded() - updateFieldsFromStickyText() } else { // Check whether note type has been changed val newModel = currentlySelectedNotetype diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/NoteFieldsCheckResult.kt b/AnkiDroid/src/main/java/com/ichi2/anki/NoteFieldsCheckResult.kt new file mode 100644 index 000000000000..307a8c4c8b79 --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/anki/NoteFieldsCheckResult.kt @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024 Ashish Yadav + * + * 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 . + */ + +package com.ichi2.anki + +import android.content.Context +import anki.notes.NoteFieldsCheckResponse +import com.ichi2.anki.CollectionManager.TR +import com.ichi2.anki.CollectionManager.withCol +import com.ichi2.anki.NoteFieldsCheckResult.* +import com.ichi2.anki.utils.ext.isImageOcclusion +import com.ichi2.libanki.Note +import timber.log.Timber + +/** + * The result of [checking note fields][Note.fieldsCheck], either a [Success], or [Failure] with + * user-readable message + * + * @see NoteFieldsCheckResponse.State + * @see checkNoteFieldsResponse + */ +sealed interface NoteFieldsCheckResult { + data object Success : NoteFieldsCheckResult + + /** @property localizedMessage user-readable error message */ + data class Failure(private val localizedMessage: String?) : NoteFieldsCheckResult { + fun getLocalizedMessage(context: Context) = localizedMessage ?: context.getString(R.string.something_wrong) + } +} + +/** + * Validates fields of a note; produces a human-readable error on failure + * + * @see NoteFieldsCheckResult + * @see Note.fieldsCheck + **/ +suspend fun checkNoteFieldsResponse(note: Note): NoteFieldsCheckResult { + Timber.d("validating note fields") + val fieldsCheckState = withCol { note.fieldsCheck(this) } + + return when (fieldsCheckState) { + NoteFieldsCheckResponse.State.NORMAL, NoteFieldsCheckResponse.State.DUPLICATE + -> Success + + NoteFieldsCheckResponse.State.EMPTY -> if (note.notetype.isImageOcclusion) { + Failure(TR.notetypesNoOcclusionCreated2()) + } else { + Failure(TR.addingTheFirstFieldIsEmpty()) + } + + NoteFieldsCheckResponse.State.MISSING_CLOZE -> + Failure(TR.addingYouHaveAClozeDeletionNote()) + + NoteFieldsCheckResponse.State.NOTETYPE_NOT_CLOZE -> + Failure(TR.addingClozeOutsideClozeNotetype()) + + NoteFieldsCheckResponse.State.FIELD_NOT_CLOZE -> + Failure(TR.addingClozeOutsideClozeField()) + + NoteFieldsCheckResponse.State.UNRECOGNIZED -> + Failure(localizedMessage = null) + } +} diff --git a/AnkiDroid/src/main/res/values/02-strings.xml b/AnkiDroid/src/main/res/values/02-strings.xml index 08567f53eac3..04d08486ae0e 100644 --- a/AnkiDroid/src/main/res/values/02-strings.xml +++ b/AnkiDroid/src/main/res/values/02-strings.xml @@ -96,8 +96,6 @@ Edit note Discard No cards created. Please fill in more fields - The first field is empty - This note type must contain cloze deletions The current note type did not produce any cards.\nPlease choose another note type, or click ‘Cards’ and add a field substitution Cloze deletions will only work on a Cloze note type Saving note diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/NoteEditorTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/NoteEditorTest.kt index 718eb4cf5eb8..9b0b207dda37 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/NoteEditorTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/NoteEditorTest.kt @@ -41,6 +41,7 @@ import com.ichi2.libanki.Decks.Companion.CURRENT_DECK import com.ichi2.libanki.Note import com.ichi2.libanki.NotetypeJson import com.ichi2.testutils.AnkiAssert.assertDoesNotThrow +import com.ichi2.testutils.getString import kotlinx.coroutines.runBlocking import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.* @@ -79,12 +80,13 @@ class NoteEditorTest : RobolectricTest() { } @Test - fun errorSavingNoteWithNoFirstFieldDisplaysNoFirstField() { + fun errorSavingNoteWithNoFirstFieldDisplaysNoFirstField() = runTest { val noteEditor = getNoteEditorAdding(NoteType.BASIC) .withNoFirstField() .build() - val actualResourceId = noteEditor.addNoteErrorResource - assertThat(actualResourceId, equalTo(R.string.note_editor_no_first_field)) + noteEditor.saveNote() + val actualResourceId = noteEditor.snackbarErrorText + assertThat(actualResourceId, equalTo(CollectionManager.TR.addingTheFirstFieldIsEmpty())) } // @Test @@ -111,30 +113,36 @@ class NoteEditorTest : RobolectricTest() { // } @Test - fun errorSavingClozeNoteWithNoFirstFieldDisplaysClozeError() { + fun errorSavingClozeNoteWithNoFirstFieldDisplaysClozeError() = runTest { val noteEditor = getNoteEditorAdding(NoteType.CLOZE) .withNoFirstField() .build() - val actualResourceId = noteEditor.addNoteErrorResource - assertThat(actualResourceId, equalTo(R.string.note_editor_no_cloze_delations)) + noteEditor.saveNote() + val actualResourceId = noteEditor.snackbarErrorText + assertThat(actualResourceId, equalTo(CollectionManager.TR.addingTheFirstFieldIsEmpty())) } @Test - fun errorSavingClozeNoteWithNoClozeDeletionsDisplaysClozeError() { + fun errorSavingClozeNoteWithNoClozeDeletionsDisplaysClozeError() = runTest { val noteEditor = getNoteEditorAdding(NoteType.CLOZE) .withFirstField("NoCloze") .build() - val actualResourceId = noteEditor.addNoteErrorResource - assertThat(actualResourceId, equalTo(R.string.note_editor_no_cloze_delations)) + noteEditor.saveNote() + val actualResourceId = noteEditor.snackbarErrorText + assertThat( + actualResourceId, + equalTo(CollectionManager.TR.addingYouHaveAClozeDeletionNote()) + ) } @Test - fun errorSavingNoteWithNoTemplatesShowsNoCardsCreated() { + fun errorSavingNoteWithNoTemplatesShowsNoCardsCreated() = runTest { val noteEditor = getNoteEditorAdding(NoteType.BACK_TO_FRONT) .withFirstField("front is not enough") .build() - val actualResourceId = noteEditor.addNoteErrorResource - assertThat(actualResourceId, equalTo(R.string.note_editor_no_cards_created)) + noteEditor.saveNote() + val actualResourceId = noteEditor.snackbarErrorText + assertThat(actualResourceId, equalTo(getString(R.string.note_editor_no_cards_created))) } @Test From 8e0db75c3b48cbbccfe4006dd56f3bbb6c58f2ce Mon Sep 17 00:00:00 2001 From: Ashish Yadav <48384865+criticalAY@users.noreply.github.com> Date: Tue, 21 May 2024 08:16:47 +0530 Subject: [PATCH 002/138] refactor: use dialog instead of snackbar for warning --- .../main/java/com/ichi2/anki/NoteEditor.kt | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt b/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt index 4c75aa500767..dea53c000e70 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt @@ -318,6 +318,7 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags SAME_NUMBER, INCREMENT_NUMBER } + @NeedsTest("Error message should be null after save") private var addNoteErrorMessage: String? = null private fun displayErrorSavingNote() { @@ -325,18 +326,24 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags // Anki allows to proceed in case we try to add non cloze text in cloze field with warning, // this snackbar helps replicate similar behaviour if (errorMessage == TR.addingYouHaveAClozeDeletionNote()) { - showSnackbar(errorMessage, Snackbar.LENGTH_INDEFINITE) { - setAction(R.string.dialog_ok) { - lifecycleScope.launch { - saveNoteWithProgress() - } - } - } + noClozeDialog(errorMessage) } else { showSnackbar(errorMessage) } } + private fun noClozeDialog(errorMessage: String) { + AlertDialog.Builder(this).show { + message(text = errorMessage) + positiveButton(text = TR.actionsSave()) { + lifecycleScope.launch { + saveNoteWithProgress() + } + } + negativeButton(R.string.dialog_cancel) + } + } + @VisibleForTesting val snackbarErrorText: String get() = when { @@ -964,7 +971,6 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags sourceText = null refreshNoteData(FieldChangeType.refreshWithStickyFields(shouldReplaceNewlines())) showSnackbar(TR.addingAdded(), Snackbar.LENGTH_SHORT) - addNoteErrorMessage = null if (caller == CALLER_NOTEEDITOR || aedictIntent) { closeEditorAfterSave = true @@ -1033,6 +1039,7 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags displayErrorSavingNote() return@launch } + addNoteErrorMessage = null saveNoteWithProgress() } } else { From a43900a8ac79a40a218615d13fe1af5a240d33a4 Mon Sep 17 00:00:00 2001 From: Ashish Yadav <48384865+criticalAY@users.noreply.github.com> Date: Sat, 18 May 2024 15:40:59 +0530 Subject: [PATCH 003/138] chore: extension method to get cloze field name and templates --- .../com/ichi2/anki/utils/CardTemplateJson.kt | 75 ++++++++++++++++ .../java/com/ichi2/anki/utils/ext/NoteType.kt | 19 ++++ .../test/java/com/ichi2/utils/NoteTypeTest.kt | 86 +++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/utils/CardTemplateJson.kt create mode 100644 AnkiDroid/src/test/java/com/ichi2/utils/NoteTypeTest.kt diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/utils/CardTemplateJson.kt b/AnkiDroid/src/main/java/com/ichi2/anki/utils/CardTemplateJson.kt new file mode 100644 index 000000000000..221214062113 --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/anki/utils/CardTemplateJson.kt @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 Ashish Yadav + * + * 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 . + */ + +package com.ichi2.anki.utils + +import com.ichi2.utils.deepClonedInto +import org.intellij.lang.annotations.Language +import org.json.JSONObject + +class CardTemplateJson : JSONObject { + /** + * Creates a new empty model object + */ + constructor() : super() + + /** + * Creates a copy from [JSONObject] and use it as a string + * + * This function will perform deepCopy on the passed object + * + * @see CardTemplateJson.from + */ + constructor(json: JSONObject) : super() { + json.deepClonedInto(this) + } + + /** + * Creates a model object form json string + */ + constructor(@Language("json") json: String) : super(json) + + val name: String + get() = getString("name") + + val ord: Int + get() = getInt("ord") + + val qfmt: String + get() = getString("qfmt") + + val afmt: String + get() = getString("afmt") + + val bqfmt: String + get() = getString("bqfmt") + + val bafmt: String + get() = getString("bafmt") + + val did: Long? + get() = if (isNull("did")) null else getLong("did") + + val bfont: String + get() = getString("bfont") + + val bsize: Int + get() = getInt("bsize") + + val id: Long + get() = getLong("id") +} diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/utils/ext/NoteType.kt b/AnkiDroid/src/main/java/com/ichi2/anki/utils/ext/NoteType.kt index 189c58df440e..46711cd69712 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/utils/ext/NoteType.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/utils/ext/NoteType.kt @@ -17,7 +17,9 @@ package com.ichi2.anki.utils.ext import anki.notetypes.StockNotetype.OriginalStockKind.ORIGINAL_STOCK_KIND_IMAGE_OCCLUSION_VALUE +import com.ichi2.anki.utils.CardTemplateJson import com.ichi2.libanki.NotetypeJson +import com.ichi2.utils.jsonObjectIterable import org.json.JSONException /** @@ -29,3 +31,20 @@ val NotetypeJson.isImageOcclusion: Boolean } catch (e: JSONException) { false } + +/** + * Regular expression pattern for extracting cloze text fields. + */ +private val clozeRegex = "\\{\\{(?:.*?:)?cloze:([^}]*)\\}\\}".toRegex() + +val NotetypeJson.templates: List + get() = getJSONArray("tmpls").jsonObjectIterable().map { CardTemplateJson(it) } + +fun NotetypeJson.getAllClozeTextFields(): List { + if (!this.isCloze) { + throw IllegalStateException("getAllClozeTextFields called on non-cloze template") + } + + val questionFormat = templates.single().qfmt + return clozeRegex.findAll(questionFormat).map { it.groups[1]!!.value }.toList() +} diff --git a/AnkiDroid/src/test/java/com/ichi2/utils/NoteTypeTest.kt b/AnkiDroid/src/test/java/com/ichi2/utils/NoteTypeTest.kt new file mode 100644 index 000000000000..17e826fb3d24 --- /dev/null +++ b/AnkiDroid/src/test/java/com/ichi2/utils/NoteTypeTest.kt @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024 Ashish Yadav + * + * 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 . + */ + +package com.ichi2.utils + +import com.ichi2.anki.utils.ext.getAllClozeTextFields +import com.ichi2.anki.utils.ext.templates +import com.ichi2.libanki.NotetypeJson +import junit.framework.TestCase.assertEquals +import kotlin.test.Test + +// link to a method in `NoteType.kt` for navigation as it contains no classes +/** Test of [NoteType][templates] */ +class NoteTypeTest { + + private val noteType = """ + { + "type":1, + "tmpls":[ + { + "name":"Cloze", + "ord":0, + "qfmt":"{{type:cloze:Text}} {{type:cloze:Text2}} {{cloze:Text3}} {{Added field}}", + "afmt":"{{cloze:Text}}
\n{{Back Extra}}", + "bqfmt":"", + "bafmt":"", + "did":null, + "bfont":"", + "bsize":0, + "id":1716321740 + } + ] + } + """ + + @Test + fun testQfmtField() { + val notetypeJson = NotetypeJson(noteType) + + val expectedQfmt = "{{type:cloze:Text}} {{type:cloze:Text2}} {{cloze:Text3}} {{Added field}}" + assertEquals(expectedQfmt, notetypeJson.templates[0].qfmt) + } + + @Test + fun testGetAllClozeTexts() { + val notetypeJson = NotetypeJson(noteType) + + val expectedClozeTexts = listOf("Text", "Text2", "Text3") + assertEquals(expectedClozeTexts, notetypeJson.getAllClozeTextFields()) + } + + @Test + fun testNameField() { + val notetypeJson = NotetypeJson(noteType) + val expectedName = "Cloze" + assertEquals(expectedName, notetypeJson.templates[0].name) + } + + @Test + fun testOrdField() { + val notetypeJson = NotetypeJson(noteType) + val expectedOrd = 0 + assertEquals(expectedOrd, notetypeJson.templates[0].ord) + } + + @Test + fun testAfmtField() { + val notetypeJson = NotetypeJson(noteType) + val expectedAfmt = "{{cloze:Text}}
\n{{Back Extra}}" + assertEquals(expectedAfmt, notetypeJson.templates[0].afmt) + } +} From 5ebb74c2751fdaf20d645807ee383b4574177892 Mon Sep 17 00:00:00 2001 From: Ashish Yadav <48384865+criticalAY@users.noreply.github.com> Date: Sun, 26 May 2024 16:37:01 +0530 Subject: [PATCH 004/138] typo: fix typo in NotetypeJson --- AnkiDroid/src/main/java/com/ichi2/libanki/NotetypeJson.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/NotetypeJson.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/NotetypeJson.kt index f278c85a2d98..67a0cd0d988c 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/NotetypeJson.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/NotetypeJson.kt @@ -51,7 +51,7 @@ class NotetypeJson : JSONObject { } /** - * Creates a model object form json string + * Creates a model object from json string */ constructor(@Language("json") json: String) : super(json) From fabbd7a3a599bb11b74f91205a2967828b893000 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Sun, 26 May 2024 21:42:51 +0100 Subject: [PATCH 005/138] fix(tags-dialog): crash on unicode tags When deserializing, we called the wrong method so there was an unknown byte as a prefix This then failed the string -> JSON conversion fixes 16476 --- .../com/ichi2/anki/dialogs/tags/TagsDialog.kt | 5 ++--- .../ichi2/anki/dialogs/tags/TagsDialogTest.kt | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/tags/TagsDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/tags/TagsDialog.kt index 1617446a0655..d51146f237c4 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/tags/TagsDialog.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/tags/TagsDialog.kt @@ -31,7 +31,6 @@ import com.ichi2.anki.R import com.ichi2.anki.analytics.AnalyticsDialogFragment import com.ichi2.anki.model.CardStateFilter import com.ichi2.anki.snackbar.showSnackbar -import com.ichi2.anki.utils.ext.convertToString import com.ichi2.annotations.NeedsTest import com.ichi2.utils.DisplayUtils.resizeWhenSoftInputShown import com.ichi2.utils.TagsUtil @@ -415,13 +414,13 @@ class TagsFile(path: String) : File(path), Parcelable { // https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/formats.md val string = Json.encodeToString(data) Timber.d("persisting tags to disk, length: %d", string.length) - outputStream.writeBytes(string) + outputStream.writeUTF(string) } } fun getData() = DataInputStream(FileInputStream(this)).use { inputStream -> // PERF!!: This takes ~2 seconds with AnKing - Json.decodeFromString(inputStream.convertToString()) + Json.decodeFromString(inputStream.readUTF()) } override fun describeContents(): Int = 0 diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/tags/TagsDialogTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/tags/TagsDialogTest.kt index 9fb19f816699..e60f14a0f1ef 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/tags/TagsDialogTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/tags/TagsDialogTest.kt @@ -44,6 +44,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito import org.mockito.kotlin.whenever +import timber.log.Timber import java.util.concurrent.atomic.AtomicReference @RunWith(AndroidJUnit4::class) @@ -636,6 +637,21 @@ class TagsDialogTest : RobolectricTest() { } } + @Test + fun `unicode tags can be serialized 16576`() { + val type = TagsDialog.DialogType.FILTER_BY_TAG + val allTags = listOf("02动作状态") + + val args = TagsDialog(ParametersUtils.whatever()) + .withTestArguments(type, emptyList(), allTags) + .arguments + val mockListener = Mockito.mock(TagsDialogListener::class.java) + val factory = TagsDialogFactory(mockListener) + val scenario = FragmentScenario.launch(TagsDialog::class.java, args, R.style.Theme_Light, factory) + scenario.moveToState(Lifecycle.State.STARTED) + scenario.onFragment { Timber.d("Dialog successfully opened") } + } + // these are called 'withTestArguments' due to "extension is shadowed by a member" warnings // this is needed so we can pass in 'targetContext' for context.cacheDir private fun TagsDialog.withTestArguments( From 77b02ec1b0a29b0c9626ef4414ee3308f8bebd6b Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Mon, 27 May 2024 12:37:25 +0000 Subject: [PATCH 006/138] Bumped version to 2.19alpha3 --- AnkiDroid/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AnkiDroid/build.gradle b/AnkiDroid/build.gradle index 1d9f32a9c7d3..db7f0a297b84 100644 --- a/AnkiDroid/build.gradle +++ b/AnkiDroid/build.gradle @@ -74,8 +74,8 @@ android { // // This ensures the correct ordering between the various types of releases (dev < alpha < beta < release) which is // needed for upgrades to be offered correctly. - versionCode=21900102 - versionName="2.19alpha2" + versionCode=21900103 + versionName="2.19alpha3" minSdk 23 // also in testlib/build.gradle.kts // After #13695: change .tests_emulator.yml targetSdk 33 // also in [api|testlib]/build.gradle.kts and ../robolectricDownloader.gradle From 0029da5e39b3f8e7009aa28878b76c130718b4a8 Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com> Date: Sat, 23 Mar 2024 12:36:42 -0300 Subject: [PATCH 007/138] feat: add new reviewer dev option currently, it does nothing. This commit is just to simplify the reviewing process --- AnkiDroid/src/main/res/values/preferences.xml | 1 + AnkiDroid/src/main/res/xml/preferences_dev_options.xml | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/AnkiDroid/src/main/res/values/preferences.xml b/AnkiDroid/src/main/res/values/preferences.xml index e88c955ab6f8..7f5730464c07 100644 --- a/AnkiDroid/src/main/res/values/preferences.xml +++ b/AnkiDroid/src/main/res/values/preferences.xml @@ -175,6 +175,7 @@ analytics_debug_preference debug_lock_database new_congrats_screen + newReviewer showOnboarding resetOnboarding devOptionsEnabledByUser diff --git a/AnkiDroid/src/main/res/xml/preferences_dev_options.xml b/AnkiDroid/src/main/res/xml/preferences_dev_options.xml index 1f6490e0b066..7a3248cc460e 100644 --- a/AnkiDroid/src/main/res/xml/preferences_dev_options.xml +++ b/AnkiDroid/src/main/res/xml/preferences_dev_options.xml @@ -44,6 +44,10 @@ android:title="Lock Database" android:summary="Touch here to lock the database (all threads block in-process, exception if using second process)" android:key="@string/pref_lock_database_key"/> + Date: Sat, 23 Mar 2024 17:04:31 -0300 Subject: [PATCH 008/138] chore: add Flow utils --- .../java/com/ichi2/anki/utils/ext/Flow.kt | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/utils/ext/Flow.kt diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/utils/ext/Flow.kt b/AnkiDroid/src/main/java/com/ichi2/anki/utils/ext/Flow.kt new file mode 100644 index 000000000000..a0cede15bcbb --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/anki/utils/ext/Flow.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 Brayan Oliveira + * + * 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 . + */ +package com.ichi2.anki.utils.ext + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch + +fun Flow.collectLatestIn(scope: CoroutineScope, action: suspend (value: T) -> Unit): Job { + return scope.launch { + collectLatest(action) + } +} + +fun Flow.collectIn(scope: CoroutineScope, collector: FlowCollector): Job { + return scope.launch { + collect(collector) + } +} From a6d077275076ab4856adac522219aeda36f90638 Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com> Date: Wed, 22 May 2024 14:43:31 -0300 Subject: [PATCH 009/138] feat: start Reviewer port the style and features are going to be implemented incrementally --- .../main/java/com/ichi2/anki/DeckPicker.kt | 9 +- .../ui/windows/reviewer/ReviewerFragment.kt | 137 +++++++++++++++++ .../ui/windows/reviewer/ReviewerViewModel.kt | 119 +++++++++++++++ AnkiDroid/src/main/res/layout/reviewer2.xml | 143 ++++++++++++++++++ AnkiDroid/src/main/res/menu/reviewer2.xml | 29 ++++ AnkiDroid/src/main/res/values/colors.xml | 9 ++ AnkiDroid/src/main/res/values/styles.xml | 5 + 7 files changed, 449 insertions(+), 2 deletions(-) create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt create mode 100644 AnkiDroid/src/main/res/layout/reviewer2.xml create mode 100644 AnkiDroid/src/main/res/menu/reviewer2.xml diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt b/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt index b9af96cf0a53..4c74215bf772 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt @@ -117,6 +117,7 @@ import com.ichi2.anki.snackbar.BaseSnackbarBuilderProvider import com.ichi2.anki.snackbar.SnackbarBuilder import com.ichi2.anki.snackbar.showSnackbar import com.ichi2.anki.ui.dialogs.storageMigrationFailedDialogIsShownOrPending +import com.ichi2.anki.ui.windows.reviewer.ReviewerFragment import com.ichi2.anki.utils.SECONDS_PER_DAY import com.ichi2.anki.widgets.DeckAdapter import com.ichi2.anki.worker.SyncMediaWorker @@ -2305,8 +2306,12 @@ open class DeckPicker : } private fun openReviewer() { - val reviewer = Intent(this, Reviewer::class.java) - reviewLauncher.launch(reviewer) + val intent = if (sharedPrefs().getBoolean("newReviewer", false)) { + ReviewerFragment.getIntent(this) + } else { + Intent(this, Reviewer::class.java) + } + reviewLauncher.launch(intent) } override fun onCreateCustomStudySession() { diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt new file mode 100644 index 000000000000..4a30002e34c4 --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2024 Brayan Oliveira + * + * 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 . + */ +package com.ichi2.anki.ui.windows.reviewer + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.MenuItem +import android.view.View +import android.webkit.WebView +import androidx.appcompat.view.menu.MenuBuilder +import androidx.appcompat.widget.ThemeUtils +import androidx.appcompat.widget.Toolbar +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.view.isVisible +import androidx.fragment.app.viewModels +import androidx.lifecycle.lifecycleScope +import com.google.android.material.appbar.MaterialToolbar +import com.google.android.material.button.MaterialButton +import com.ichi2.anki.AbstractFlashcardViewer.Companion.RESULT_NO_MORE_CARDS +import com.ichi2.anki.R +import com.ichi2.anki.cardviewer.CardMediaPlayer +import com.ichi2.anki.previewer.CardViewerActivity +import com.ichi2.anki.previewer.CardViewerFragment +import com.ichi2.anki.snackbar.BaseSnackbarBuilderProvider +import com.ichi2.anki.snackbar.SnackbarBuilder +import com.ichi2.anki.snackbar.showSnackbar +import com.ichi2.anki.utils.ext.collectIn +import com.ichi2.anki.utils.ext.collectLatestIn +import com.ichi2.anki.utils.navBarNeedsScrim +import com.ichi2.utils.increaseHorizontalPaddingOfOverflowMenuIcons + +class ReviewerFragment : + CardViewerFragment(R.layout.reviewer2), + BaseSnackbarBuilderProvider, + Toolbar.OnMenuItemClickListener { + + override val viewModel: ReviewerViewModel by viewModels { + ReviewerViewModel.factory(CardMediaPlayer()) + } + + override val webView: WebView + get() = requireView().findViewById(R.id.webview) + + override val baseSnackbarBuilder: SnackbarBuilder = { + anchorView = this@ReviewerFragment.view?.findViewById(R.id.buttons_area) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + setupAnswerButtons(view) + + view.findViewById(R.id.toolbar).apply { + setOnMenuItemClickListener(this@ReviewerFragment) + setNavigationOnClickListener { requireActivity().onBackPressedDispatcher.onBackPressed() } + (menu as? MenuBuilder)?.let { + it.setOptionalIconsVisible(true) + requireContext().increaseHorizontalPaddingOfOverflowMenuIcons(it) + } + } + + with(requireActivity()) { + if (!navBarNeedsScrim) { + window.navigationBarColor = + ThemeUtils.getThemeAttrColor(this, R.attr.alternativeBackgroundColor) + } + } + + viewModel.isQueueFinishedFlow.collectIn(lifecycleScope) { isQueueFinished -> + if (isQueueFinished) { + requireActivity().run { + setResult(RESULT_NO_MORE_CARDS) + finish() + } + } + } + } + + // TODO + override fun onMenuItemClick(item: MenuItem?): Boolean { + showSnackbar("Not implemented yet") + return true + } + + private fun setupAnswerButtons(view: View) { + view.findViewById(R.id.again_button).setOnClickListener { + viewModel.answerAgain() + } + view.findViewById(R.id.hard_button).setOnClickListener { + viewModel.answerHard() + } + view.findViewById(R.id.good_button).setOnClickListener { + viewModel.answerGood() + } + view.findViewById(R.id.easy_button).setOnClickListener { + viewModel.answerEasy() + } + + val showAnswerButton = view.findViewById(R.id.show_answer).apply { + setOnClickListener { + viewModel.showAnswer() + } + } + val answerButtonsLayout = view.findViewById(R.id.answer_buttons) + + // TODO add some kind of feedback/animation after tapping show answer or the answer buttons + viewModel.showingAnswer.collectLatestIn(lifecycleScope) { shouldShowAnswer -> + if (shouldShowAnswer) { + showAnswerButton.isVisible = false + answerButtonsLayout.isVisible = true + } else { + showAnswerButton.isVisible = true + answerButtonsLayout.isVisible = false + } + } + } + + companion object { + fun getIntent(context: Context): Intent { + return CardViewerActivity.getIntent(context, ReviewerFragment::class) + } + } +} diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt new file mode 100644 index 000000000000..f22ffcd4de6d --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2024 Brayan Oliveira + * + * 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 . + */ +package com.ichi2.anki.ui.windows.reviewer + +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewmodel.initializer +import androidx.lifecycle.viewmodel.viewModelFactory +import com.ichi2.anki.CollectionManager.withCol +import com.ichi2.anki.Ease +import com.ichi2.anki.asyncIO +import com.ichi2.anki.cardviewer.CardMediaPlayer +import com.ichi2.anki.launchCatchingIO +import com.ichi2.anki.previewer.CardViewerViewModel +import com.ichi2.anki.reviewer.CardSide +import com.ichi2.libanki.sched.CurrentQueueState +import com.ichi2.libanki.undoableOp +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.flow.MutableSharedFlow + +class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel(cardMediaPlayer) { + + private var queueState: Deferred = asyncIO { + // this assumes that the Reviewer won't be launched if there isn't a queueState + withCol { sched.currentQueueState() }!! + } + override var currentCard = asyncIO { + queueState.await()!!.topCard + } + var isQueueFinishedFlow = MutableSharedFlow() + + /* ********************************************************************************************* + ************************ Public methods: meant to be used by the View ************************** + ********************************************************************************************* */ + + override fun onPageFinished(isAfterRecreation: Boolean) { + if (isAfterRecreation) { + launchCatchingIO { + // TODO handle "Don't keep activities" + if (showingAnswer.value) showAnswerInternal() else showQuestion() + } + } else { + launchCatchingIO { + updateCurrentCard() + } + } + } + + fun showAnswer() { + launchCatchingIO { + showAnswerInternal() + loadAndPlaySounds(CardSide.ANSWER) + } + } + + fun answerAgain() = answerCard(Ease.AGAIN) + fun answerHard() = answerCard(Ease.HARD) + fun answerGood() = answerCard(Ease.GOOD) + fun answerEasy() = answerCard(Ease.EASY) + + /* ********************************************************************************************* + *************************************** Internal methods *************************************** + ********************************************************************************************* */ + + private fun answerCard(ease: Ease) { + launchCatchingIO { + queueState.await()?.let { + undoableOp { sched.answerCard(it, ease.value) } + updateCurrentCard() + } + } + } + + private suspend fun loadAndPlaySounds(side: CardSide) { + cardMediaPlayer.loadCardSounds(currentCard.await()) + cardMediaPlayer.playAllSoundsForSide(side) + } + + private suspend fun updateCurrentCard() { + queueState = asyncIO { + withCol { + sched.currentQueueState() + } + } + queueState.await()?.let { + currentCard = CompletableDeferred(it.topCard) + showQuestion() + loadAndPlaySounds(CardSide.QUESTION) + } ?: isQueueFinishedFlow.emit(true) + } + + // TODO + override suspend fun typeAnsFilter(text: String): String { + return text + } + + companion object { + fun factory(soundPlayer: CardMediaPlayer): ViewModelProvider.Factory { + return viewModelFactory { + initializer { + ReviewerViewModel(soundPlayer) + } + } + } + } +} diff --git a/AnkiDroid/src/main/res/layout/reviewer2.xml b/AnkiDroid/src/main/res/layout/reviewer2.xml new file mode 100644 index 000000000000..f2ed634dc489 --- /dev/null +++ b/AnkiDroid/src/main/res/layout/reviewer2.xml @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AnkiDroid/src/main/res/menu/reviewer2.xml b/AnkiDroid/src/main/res/menu/reviewer2.xml new file mode 100644 index 000000000000..ea7c0d8099cb --- /dev/null +++ b/AnkiDroid/src/main/res/menu/reviewer2.xml @@ -0,0 +1,29 @@ + + + + + + \ No newline at end of file diff --git a/AnkiDroid/src/main/res/values/colors.xml b/AnkiDroid/src/main/res/values/colors.xml index 53625c8a0d62..f3cc206a9326 100644 --- a/AnkiDroid/src/main/res/values/colors.xml +++ b/AnkiDroid/src/main/res/values/colors.xml @@ -126,5 +126,14 @@ #FF4747 #6FF06F #444444 + + #ffFFCDD2 + @color/material_red_900 + #FFE0B2 + #B33800 + #C8E6C9 + @color/material_green_900 + @color/material_light_blue_100 + @color/material_light_blue_900 diff --git a/AnkiDroid/src/main/res/values/styles.xml b/AnkiDroid/src/main/res/values/styles.xml index 317d60e53b03..d2da90259c0b 100644 --- a/AnkiDroid/src/main/res/values/styles.xml +++ b/AnkiDroid/src/main/res/values/styles.xml @@ -29,6 +29,11 @@ @drawable/bg_popup + + + + diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/ActivityStartupUnderBackupTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/ActivityStartupUnderBackupTest.kt index 4207a0d9ab81..e6949e7a453e 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/ActivityStartupUnderBackupTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/ActivityStartupUnderBackupTest.kt @@ -18,6 +18,7 @@ package com.ichi2.anki import android.app.Activity import android.os.Looper.getMainLooper import com.canhub.cropper.CropImageActivity +import com.ichi2.anki.instantnoteeditor.InstantNoteEditorActivity import com.ichi2.anki.preferences.Preferences import com.ichi2.testutils.ActivityList import com.ichi2.testutils.ActivityList.ActivityLaunchParam @@ -54,6 +55,7 @@ class ActivityStartupUnderBackupTest : RobolectricTest() { notYetHandled(Preferences::class.java.simpleName, "Not working (or implemented) - inherits from AppCompatPreferenceActivity") notYetHandled(FilteredDeckOptions::class.java.simpleName, "Not working (or implemented) - inherits from AppCompatPreferenceActivity") notYetHandled(SingleFragmentActivity::class.java.simpleName, "Implemented, but the test fails because the activity throws if a specific intent extra isn't set") + notYetHandled(InstantNoteEditorActivity::class.java.simpleName, "Single instance activity so should be used") } /** diff --git a/AnkiDroid/src/test/java/com/ichi2/testutils/ActivityList.kt b/AnkiDroid/src/test/java/com/ichi2/testutils/ActivityList.kt index c27a795efb34..437e5d1227f8 100644 --- a/AnkiDroid/src/test/java/com/ichi2/testutils/ActivityList.kt +++ b/AnkiDroid/src/test/java/com/ichi2/testutils/ActivityList.kt @@ -23,6 +23,7 @@ import com.canhub.cropper.CropImageActivity import com.ichi2.anki.* import com.ichi2.anki.CardTemplateBrowserAppearanceEditor.Companion.INTENT_ANSWER_FORMAT import com.ichi2.anki.CardTemplateBrowserAppearanceEditor.Companion.INTENT_QUESTION_FORMAT +import com.ichi2.anki.instantnoteeditor.InstantNoteEditorActivity import com.ichi2.anki.multimediacard.activity.MultimediaEditFieldActivity import com.ichi2.anki.notetype.ManageNotetypes import com.ichi2.anki.preferences.Preferences @@ -73,7 +74,8 @@ object ActivityList { get(ManageSpaceActivity::class.java), get(PermissionsActivity::class.java), get(SingleFragmentActivity::class.java), - get(CardViewerActivity::class.java) + get(CardViewerActivity::class.java), + get(InstantNoteEditorActivity::class.java) ) } From 2f3d1b3294069088c7b6aafbfd42982a1199e3e7 Mon Sep 17 00:00:00 2001 From: AnkiDroid Translations Date: Sat, 1 Jun 2024 13:51:28 +0000 Subject: [PATCH 021/138] Updated strings from Crowdin --- AnkiDroid/src/main/res/values-af/01-core.xml | 2 + AnkiDroid/src/main/res/values-am/01-core.xml | 2 + AnkiDroid/src/main/res/values-ar/01-core.xml | 2 + AnkiDroid/src/main/res/values-az/01-core.xml | 2 + AnkiDroid/src/main/res/values-be/01-core.xml | 2 + AnkiDroid/src/main/res/values-bg/01-core.xml | 2 + AnkiDroid/src/main/res/values-bn/01-core.xml | 2 + AnkiDroid/src/main/res/values-ca/01-core.xml | 2 + AnkiDroid/src/main/res/values-ckb/01-core.xml | 2 + AnkiDroid/src/main/res/values-cs/01-core.xml | 2 + AnkiDroid/src/main/res/values-da/01-core.xml | 2 + AnkiDroid/src/main/res/values-de/01-core.xml | 2 + AnkiDroid/src/main/res/values-el/01-core.xml | 2 + AnkiDroid/src/main/res/values-eo/01-core.xml | 2 + .../src/main/res/values-es-rAR/01-core.xml | 2 + .../src/main/res/values-es-rES/01-core.xml | 2 + AnkiDroid/src/main/res/values-et/01-core.xml | 2 + AnkiDroid/src/main/res/values-eu/01-core.xml | 2 + AnkiDroid/src/main/res/values-fa/01-core.xml | 2 + AnkiDroid/src/main/res/values-fi/01-core.xml | 2 + AnkiDroid/src/main/res/values-fil/01-core.xml | 90 +++++----- .../src/main/res/values-fil/03-dialogs.xml | 160 +++++++++--------- AnkiDroid/src/main/res/values-fr/01-core.xml | 2 + AnkiDroid/src/main/res/values-fy/01-core.xml | 2 + AnkiDroid/src/main/res/values-ga/01-core.xml | 2 + AnkiDroid/src/main/res/values-gl/01-core.xml | 2 + AnkiDroid/src/main/res/values-got/01-core.xml | 2 + AnkiDroid/src/main/res/values-gu/01-core.xml | 2 + AnkiDroid/src/main/res/values-heb/01-core.xml | 2 + AnkiDroid/src/main/res/values-hi/01-core.xml | 2 + AnkiDroid/src/main/res/values-hr/01-core.xml | 2 + AnkiDroid/src/main/res/values-hu/01-core.xml | 2 + AnkiDroid/src/main/res/values-hy/01-core.xml | 2 + AnkiDroid/src/main/res/values-ind/01-core.xml | 2 + AnkiDroid/src/main/res/values-is/01-core.xml | 2 + AnkiDroid/src/main/res/values-it/01-core.xml | 2 + AnkiDroid/src/main/res/values-iw/01-core.xml | 2 + AnkiDroid/src/main/res/values-ja/01-core.xml | 2 + AnkiDroid/src/main/res/values-jv/01-core.xml | 2 + AnkiDroid/src/main/res/values-ka/01-core.xml | 2 + AnkiDroid/src/main/res/values-kk/01-core.xml | 2 + AnkiDroid/src/main/res/values-km/01-core.xml | 2 + AnkiDroid/src/main/res/values-kn/01-core.xml | 2 + AnkiDroid/src/main/res/values-ko/01-core.xml | 2 + AnkiDroid/src/main/res/values-ku/01-core.xml | 2 + AnkiDroid/src/main/res/values-ky/01-core.xml | 2 + AnkiDroid/src/main/res/values-lt/01-core.xml | 2 + AnkiDroid/src/main/res/values-lv/01-core.xml | 2 + AnkiDroid/src/main/res/values-mk/01-core.xml | 2 + AnkiDroid/src/main/res/values-ml/01-core.xml | 2 + AnkiDroid/src/main/res/values-mn/01-core.xml | 2 + AnkiDroid/src/main/res/values-mr/01-core.xml | 2 + AnkiDroid/src/main/res/values-ms/01-core.xml | 2 + AnkiDroid/src/main/res/values-my/01-core.xml | 2 + AnkiDroid/src/main/res/values-nl/01-core.xml | 2 + AnkiDroid/src/main/res/values-nn/01-core.xml | 2 + AnkiDroid/src/main/res/values-no/01-core.xml | 2 + AnkiDroid/src/main/res/values-or/01-core.xml | 2 + AnkiDroid/src/main/res/values-pa/01-core.xml | 2 + AnkiDroid/src/main/res/values-pl/01-core.xml | 2 + .../src/main/res/values-pt-rBR/01-core.xml | 2 + .../src/main/res/values-pt-rPT/01-core.xml | 2 + AnkiDroid/src/main/res/values-ro/01-core.xml | 2 + AnkiDroid/src/main/res/values-ru/01-core.xml | 2 + AnkiDroid/src/main/res/values-sat/01-core.xml | 2 + AnkiDroid/src/main/res/values-sc/01-core.xml | 2 + AnkiDroid/src/main/res/values-sk/01-core.xml | 2 + AnkiDroid/src/main/res/values-sl/01-core.xml | 2 + AnkiDroid/src/main/res/values-sq/01-core.xml | 2 + AnkiDroid/src/main/res/values-sr/01-core.xml | 2 + AnkiDroid/src/main/res/values-ss/01-core.xml | 2 + AnkiDroid/src/main/res/values-sv/01-core.xml | 2 + AnkiDroid/src/main/res/values-sw/01-core.xml | 2 + AnkiDroid/src/main/res/values-ta/01-core.xml | 2 + AnkiDroid/src/main/res/values-te/01-core.xml | 2 + AnkiDroid/src/main/res/values-tg/01-core.xml | 2 + AnkiDroid/src/main/res/values-tgl/01-core.xml | 2 + AnkiDroid/src/main/res/values-th/01-core.xml | 2 + AnkiDroid/src/main/res/values-ti/01-core.xml | 2 + AnkiDroid/src/main/res/values-tn/01-core.xml | 2 + AnkiDroid/src/main/res/values-tr/01-core.xml | 2 + AnkiDroid/src/main/res/values-ts/01-core.xml | 2 + AnkiDroid/src/main/res/values-tt/01-core.xml | 2 + AnkiDroid/src/main/res/values-uk/01-core.xml | 2 + AnkiDroid/src/main/res/values-ur/01-core.xml | 2 + AnkiDroid/src/main/res/values-uz/01-core.xml | 2 + AnkiDroid/src/main/res/values-ve/01-core.xml | 2 + AnkiDroid/src/main/res/values-vi/01-core.xml | 2 + AnkiDroid/src/main/res/values-wo/01-core.xml | 2 + AnkiDroid/src/main/res/values-xh/01-core.xml | 2 + AnkiDroid/src/main/res/values-yue/01-core.xml | 2 + .../src/main/res/values-zh-rCN/01-core.xml | 2 + .../src/main/res/values-zh-rTW/01-core.xml | 2 + AnkiDroid/src/main/res/values-zu/01-core.xml | 2 + .../ankidroid-titles.txt | 2 +- 95 files changed, 311 insertions(+), 125 deletions(-) diff --git a/AnkiDroid/src/main/res/values-af/01-core.xml b/AnkiDroid/src/main/res/values-af/01-core.xml index 2d035e9d456b..d15f8f7c376f 100644 --- a/AnkiDroid/src/main/res/values-af/01-core.xml +++ b/AnkiDroid/src/main/res/values-af/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-am/01-core.xml b/AnkiDroid/src/main/res/values-am/01-core.xml index 8235179ea6a9..2a0dd54cb663 100644 --- a/AnkiDroid/src/main/res/values-am/01-core.xml +++ b/AnkiDroid/src/main/res/values-am/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-ar/01-core.xml b/AnkiDroid/src/main/res/values-ar/01-core.xml index 14f47e576788..96a9542694f1 100644 --- a/AnkiDroid/src/main/res/values-ar/01-core.xml +++ b/AnkiDroid/src/main/res/values-ar/01-core.xml @@ -270,4 +270,6 @@ الوصول إلى كل الملفات صورة معماة حذف الحساب + + Instant card diff --git a/AnkiDroid/src/main/res/values-az/01-core.xml b/AnkiDroid/src/main/res/values-az/01-core.xml index b90d488dc86c..f4ee09406e1b 100644 --- a/AnkiDroid/src/main/res/values-az/01-core.xml +++ b/AnkiDroid/src/main/res/values-az/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-be/01-core.xml b/AnkiDroid/src/main/res/values-be/01-core.xml index 2cd5bf7478da..762aa7d0c080 100644 --- a/AnkiDroid/src/main/res/values-be/01-core.xml +++ b/AnkiDroid/src/main/res/values-be/01-core.xml @@ -258,4 +258,6 @@ Доступ да ўсіх файлаў Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-bg/01-core.xml b/AnkiDroid/src/main/res/values-bg/01-core.xml index e43ea074c105..c76559c6c3ee 100644 --- a/AnkiDroid/src/main/res/values-bg/01-core.xml +++ b/AnkiDroid/src/main/res/values-bg/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-bn/01-core.xml b/AnkiDroid/src/main/res/values-bn/01-core.xml index b4860fe765a4..7c7caf53a76a 100644 --- a/AnkiDroid/src/main/res/values-bn/01-core.xml +++ b/AnkiDroid/src/main/res/values-bn/01-core.xml @@ -244,4 +244,6 @@ সব ফাইলের অ্যাক্সেস ছবিতে শূন্য স্থান পূরণ করা অ্যাকাউন্ট মুছে ফেলুন + + Instant card diff --git a/AnkiDroid/src/main/res/values-ca/01-core.xml b/AnkiDroid/src/main/res/values-ca/01-core.xml index 1a4a5e33cddd..d726512b1faf 100644 --- a/AnkiDroid/src/main/res/values-ca/01-core.xml +++ b/AnkiDroid/src/main/res/values-ca/01-core.xml @@ -244,4 +244,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-ckb/01-core.xml b/AnkiDroid/src/main/res/values-ckb/01-core.xml index fcfde3eee53a..01b4da7dd063 100644 --- a/AnkiDroid/src/main/res/values-ckb/01-core.xml +++ b/AnkiDroid/src/main/res/values-ckb/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-cs/01-core.xml b/AnkiDroid/src/main/res/values-cs/01-core.xml index 3ff8a71982de..d534378cccd2 100644 --- a/AnkiDroid/src/main/res/values-cs/01-core.xml +++ b/AnkiDroid/src/main/res/values-cs/01-core.xml @@ -258,4 +258,6 @@ Přístup ke všem souborům Okluze obrázku Odebrat účet + + Instant card diff --git a/AnkiDroid/src/main/res/values-da/01-core.xml b/AnkiDroid/src/main/res/values-da/01-core.xml index 62338f0392b0..a6511318fca3 100644 --- a/AnkiDroid/src/main/res/values-da/01-core.xml +++ b/AnkiDroid/src/main/res/values-da/01-core.xml @@ -246,4 +246,6 @@ Adgang til alle filer Billedblænding Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-de/01-core.xml b/AnkiDroid/src/main/res/values-de/01-core.xml index a39e7908a00f..6c7a5850997e 100644 --- a/AnkiDroid/src/main/res/values-de/01-core.xml +++ b/AnkiDroid/src/main/res/values-de/01-core.xml @@ -246,4 +246,6 @@ Zugang zu allen Daten Bildverdeckung Konto entfernen + + Instant card diff --git a/AnkiDroid/src/main/res/values-el/01-core.xml b/AnkiDroid/src/main/res/values-el/01-core.xml index 210dfad26844..f9e2d20eee4d 100644 --- a/AnkiDroid/src/main/res/values-el/01-core.xml +++ b/AnkiDroid/src/main/res/values-el/01-core.xml @@ -244,4 +244,6 @@ Πρόσβαση σε όλα τα αρχεία Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-eo/01-core.xml b/AnkiDroid/src/main/res/values-eo/01-core.xml index b5e2fe3027bb..a92796087d67 100644 --- a/AnkiDroid/src/main/res/values-eo/01-core.xml +++ b/AnkiDroid/src/main/res/values-eo/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-es-rAR/01-core.xml b/AnkiDroid/src/main/res/values-es-rAR/01-core.xml index c1b62478877a..d669ead09af3 100644 --- a/AnkiDroid/src/main/res/values-es-rAR/01-core.xml +++ b/AnkiDroid/src/main/res/values-es-rAR/01-core.xml @@ -243,4 +243,6 @@ Acceso a todos los archivos Imagen oculta Quitar cuenta + + Instant card diff --git a/AnkiDroid/src/main/res/values-es-rES/01-core.xml b/AnkiDroid/src/main/res/values-es-rES/01-core.xml index 93751d8a4978..533025dcce50 100644 --- a/AnkiDroid/src/main/res/values-es-rES/01-core.xml +++ b/AnkiDroid/src/main/res/values-es-rES/01-core.xml @@ -243,4 +243,6 @@ Acceso a todos los archivos Imagen oculta Quitar cuenta + + Instant card diff --git a/AnkiDroid/src/main/res/values-et/01-core.xml b/AnkiDroid/src/main/res/values-et/01-core.xml index bcf47b66027a..fdd328cef84b 100644 --- a/AnkiDroid/src/main/res/values-et/01-core.xml +++ b/AnkiDroid/src/main/res/values-et/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-eu/01-core.xml b/AnkiDroid/src/main/res/values-eu/01-core.xml index cd37b23431c6..b517633c7d0f 100644 --- a/AnkiDroid/src/main/res/values-eu/01-core.xml +++ b/AnkiDroid/src/main/res/values-eu/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-fa/01-core.xml b/AnkiDroid/src/main/res/values-fa/01-core.xml index 511b049de297..49b0469a6093 100644 --- a/AnkiDroid/src/main/res/values-fa/01-core.xml +++ b/AnkiDroid/src/main/res/values-fa/01-core.xml @@ -245,4 +245,6 @@ دسترسی به همه فایل ها Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-fi/01-core.xml b/AnkiDroid/src/main/res/values-fi/01-core.xml index 341e701b41fa..808a61503464 100644 --- a/AnkiDroid/src/main/res/values-fi/01-core.xml +++ b/AnkiDroid/src/main/res/values-fi/01-core.xml @@ -246,4 +246,6 @@ Pääsy kaikkiin tiedostoihin Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-fil/01-core.xml b/AnkiDroid/src/main/res/values-fil/01-core.xml index 9f2d6ee82aa0..885bdc555dc8 100644 --- a/AnkiDroid/src/main/res/values-fil/01-core.xml +++ b/AnkiDroid/src/main/res/values-fil/01-core.xml @@ -60,18 +60,18 @@ Palawakin Itiklop - %d natitirang minuto - %d minutes left + %d minutong natitira + %d minutong natitira - %1$d oras %2$d pa ang natititra - %1$d hours %2$d left + %1$d oras %2$d ang natititra + %1$d oras %2$d ang natititra - %1$d day %2$d left - %1$d araw %2$d pa ang natititra + %1$d araw %2$d ang natititra + %1$d araw %2$d ang natititra - Walang laman ang tipon + Walang laman ang koleksyon Magsimulang magdadag ng mga cards\n gamit ang + na aykon. @@ -174,23 +174,23 @@ Card Browser Anki Card - Hindi maipagsama ang mga tipon.\nAlin sa mga tipon ang nais mong panatilihin? + Hindi maipagsama ang mga koleksyon.\nAlin sa mga koleksyon ang nais mong panatilihin? AnkiDroid AnkiWeb - Palitan ang tipon mo sa AnkiDroid ng tipon mo mula sa AnkiWeb? - Palitan ang tipon mo sa AnkiWeb ng tipon mo mula sa AnkiDroid? - Piliin ang tipon na nais mong panatilihin - Palitan ang tipon + Palitan ang koleksyon mo sa AnkiDroid ng koleksyon mo mula sa AnkiWeb? + Palitan ang koleksyon mo sa AnkiWeb ng koleksyon mo mula sa AnkiDroid? + Piliin ang koleksyon na panatilihin + Pinapalitan ang koleksyon %1$d na card (0 takda) %1$d na mga card (0 takda) Hindi maisulat o magawa ang file na %s - "Multiple errors, most recent: %s" - Multiple consecutive errors without progress, most recent: %s + "Maraming mga mali, pinakabago: %s" + Maraming sunod-sunod na mga mali na walang usad, pinakabago: %s - Migrating database files + Nililipat ang mga file pang-database Kinokopya… Nililipat ang mga media Kinakalkula ang laki ng ililipat… @@ -201,48 +201,50 @@ \n \nTandaan na ang iyong koleksyon ay matatagpuan sa isang folder na matatanggal sa panahong buburahin ang app. Siguraduhing ligtas ang iyong datos sa pamamagitan ng madalas na pag-sync o pag-export ng mga backup.
- Migration failed - Pumalya ang paglilipat +
- The changes were reverted. + Binalik sa dati ang mga pinalitan.

- Please try re-running the migration. - To resolve the problem, you may need to free up some disk space, - or reconnect the removable storage that holds your collection. + Mangyaring subukan muling paganahin ang paglipat. + Para maresolba ang problema, maaaring kailangan magbura para magkaroon pa ng space, + o ikonekta muli ang natatanggal na storage na naglalaman ng iyong koleksyon.

- Learn more and get help + Alamin pa at humingi ng tulong ]]>
-
- The changes were not reverted. - While no data should’ve been lost, - the media files might be split between the old and the new folder. + Hindi naibalik sa dati ang mga pinalitan. + Kahit na walang datos ang dapat mawala, + maaaring nahati ang mga media na file sa pagitan ng luma at bagong folder.

- Please try re-running the migration. - To resolve the problem, you may need to free up some disk space, - or reconnect the removable storage that holds your collection. + Mangyaring paganahin muli ang paglipat. + Para maresolba ang problema, maaaring kailangan magbura para magkaroon pa ng space, + o ikonekta muli ang natatanggal na storage na naglalaman ng iyong koleksyon.

- Learn more and get help + Alamin pa at humingi ng tulong ]]>
-
- Learn more and get help + Alamin pa at humingi ng tulong ]]>
- Resume migration - Hindi ma-access ang tipon - Hindi namin ma-access ang iyong tipon matapos ma-uninstall ang AnkiDroid dahil sa bagong polisiya ng Play Store\n\nLigtas ang iyong data at maari itong i-restore. Makikita it sa\n%s\n\nPumili ng opsyon sa ibaba upang ma-restore: - Android has removed AnkiDroid\'s %1$s permission due to app inactivity.\n\nYour data is safe and can be restored. It is located at\n%2$s\n\nSelect an option below to restore: + Ipapatuloy ang paglilipat + Hindi ma-access ang koleksyon + Hindi namin ma-access ang iyong koleksyon matapos ma-uninstall ang AnkiDroid dahil sa bagong polisiya ng Play Store\n\nLigtas ang iyong data at maari itong ibalik. Makikita ito sa\n%s\n\nPumili ng opsyon sa ibaba upang maibalik: + Tinanggal ng Android ang mga permiso ng AnkiDroid sa %1$s dahil sa hindi madalas na paggamit sa app.\n\nLigtas ang iyong datos at maaari itong ibalik. Mahahanap ito sa \n%2$s\n\nPumili ng opsyon sa ibaba para maibalik: Mag-restore mula sa AnkiWeb (nirerekomenda) I-restore ang access sa folder (nirerekomenda) I-restore ang access sa folder (dalubhasa) Mag-restore mula sa backup na .colpkg (advanced) - Lumikha ng bagong tipon - Mabubura ang bagong tipon mula sa iyong phone sakaling i-uninstall mo ang AnkiDroid + Lumikha ng bagong koleksyon + Mabubura ang bagong koleksyon mula sa iyong phone sakaling i-uninstall mo ang AnkiDroid - AnkiDroid needs some permissions to work - Storage access - Saves your collection in a safe place that will not be deleted if the app is uninstalled - All files access - Image Occlusion - Remove account + Kailangan ng mga permiso ang AnkiDroid upang gumana + Access sa storage + I-save ang iyong koleksyon sa ligtas na lugar nang hindi ito mabura kapag inuninstall ang app. + Access sa lahat ng mga file + Oklusyon ng Imahe + Burahin ang account + + Instant card diff --git a/AnkiDroid/src/main/res/values-fil/03-dialogs.xml b/AnkiDroid/src/main/res/values-fil/03-dialogs.xml index 49991eb9109a..20afd024bec9 100644 --- a/AnkiDroid/src/main/res/values-fil/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fil/03-dialogs.xml @@ -44,7 +44,7 @@ ~ this program. If not, see . --> - I-tsek ang database? + Suriin ang database? It ay maaaring tumagal ng mahabang oras Burahin ang deck Burahin ang deck? @@ -69,25 +69,25 @@ %d mga card ang naiskedyul muli Database error - Writing to the collection failed. The database could be corrupt or there may not to be enough empty space on disk.\n\nIf this happens more often, try checking the database, repairing the collection or restoring it from a backup. Touch “options” for that.\n\Or it could be an AnkiDroid bug as well; please report the error so that we can check this. + Ang pagsulat sa koleksyon ay nabigo. Maaaring sira ang database o di kaya`y hindi sapat ang bakanteng space sa disk. \n\n Kung ito ay nangyayari ng madalas, subukang tignan ang database, ayusin ang koleksyon o ibalik ito mula sa isang backup. Pindutin ang \"mga opsyon\" para diyan. \n\Maaaring ito rin ay isang AnkiDroid bug; i-ulat ang mali upang maiayos namin ito. Maling ulat - There is not enough free storage space to open AnkiDroid. Free up some space to continue. + Hindi sapat ang bakanteng storage upang buksan ang AnkiDroid. Magbukas pa ng space para makapagpatuloy. Gusto mo ba talagang subukan ang pag-aayos ng database? \n\n Bago mo simulan ang pagtatangka, isang kopya ang lilikhain sa mga subfolder \"%s\". Ang kategoryang \"default\" ay walng laman Upang magdagdag ng mga kard sa AnkiDroid alisin lahat ng mga kategorya ng Notepad o magdagdag ng isa na pinangalanang \"default\" Mga bagong kard sa deck:%d Mga review na nakatakda sa deck:%d - Increase/decrease (“-3”) today’s new card limit by - Increase/decrease (“-3”) today’s review limit by + Dagdagan/bawasan (\"-3\") ang hangganan ng bagong card ngayong araw ng + Dagdagan/bawasan (\"-3\") ang hangganan ng pagrepaso ngayong araw ng Ang mga review kard na nakalimutan sa huling x araw: Suriin nang maaga ng x araw: Pumili ng x kard sa pamamagitan ng random mula sa deck: I-preview ang mga bagong kjard na naidagdag sa mga huling x araw: - Could not rebuild custom study deck + Hindi maisaayos muli ang custom na deck pang-aral Puno na ang storage Malapit nang mapuno ang storage Walang espasyo - AnkiDroid needs %s free storage space to continue. Please clear some space + Kailangan ng AnkiDroid ng %s na bakanteng storage space para makapagpatuloy. Mangyaring magbukas pa ng space. Ibalik ang backup? Ang iyong koleksyon ay mapapalitan ng mas lumang kopya. Ang anumang pag-unlad na hindi na - isave ay mawawala. Pumili ng iba pa @@ -142,115 +142,115 @@ Mga file na may di-wastong pag-encode:%d Audio recording permission denied Unknown error occurred displaying Advanced Editor - AnkiDroid Upgraded - AnkiDroid has been upgraded. This upgrade includes fixes for possible database problems, and we advise you to run check database now. - Continue Anyway - Check Database uses a large amount of temporary storage.\n\nIt is strongly recommended that you have at least %s free space on your device before continuing. - \n\nYou currently have %s free. + Na-upgrade ang AnkiDroid + Na-upgrade na ang AnkiDroid. Ang upgrade na ito ay naglalaman ng pag-aayos sa mga posibleng problema sa database, at pinapayuhan ka namin na suriin ang database ngayon. + Magpatuloy pa rin + Ang pagsuri ng database ay gagamit ng malaking panandaliang storage.\n\nLabis na nirerekomenda na mayroon kang hindi bababa sa %s na bakanteng space sa iyong device bago magpatuloy. + \n\nMayroon kang %s na bakante. - Error decoding data from card + May mali sa pag-decode sa datos mula sa iyong card - Database Locked - The AnkiDroid database is in use by another application. Please close the other application then reopen AnkiDroid. - Incompatible Database Version - The database is a more advanced version than this version of AnkiDroid can work with. Upgrade AnkiDroid or downgrade the database to open it\n\nSupported version: %1$d\nDatabase version: %2$d\n\nThe following restore options will overwrite your current collection, possibly with a compatible database version: + Nakakandado ang Database + Ginagamit ng ibang aplikasyon ang database ng AnkiDroid. Mangyaring isara ang ibang aplikasyon at buksan muli ang AnkiDroid. + Hindi Angkop Ang Bersyon ng Database + Mas abante ang database na ito kumpara sa bersyong kayang gamitin ng AnkiDroid. I-upgrade o i-downgrade ang database ng AnkiDroid upang mabuksan ito\n\nBersyon na suportado: %1$d\nBersyon ng database: %2$d\n\nAng sumusunod na mga opsyon sa pagbalik ay posibleng sapawan ang kasalukuyan mong koleksyon ng isang angkop na bersyon ng database. - Background image applied + Na-apply ang larawan sa background Background image removed - No image selected - Error selecting image. Please see manual. %s - Error deleting image - Failed to apply background image %s - Deck Picker background too large - Maximum image size %d MB allowed - Image dimensions are too large (%1$d × %2$d) + Walang napiling larawan + May mali sa pagpili ng larawan. Mangyari na tingnan ang gabay. %s + May mali sa pagbura ng larawan + Bigong ilagay ang background na larawan %s + Masyadong malaki ang background ng Deck Picker + Hanggang %d MB lamang ang pupwedeng laki ng larawan + Masyadong malaki ang sukat ng larawan (%1$d x%2$d) - Missing required storage permission. Please grant storage permission then retry your action. + Kulang ang kinakailangang permiso sa storage. Mangyaring bigyang permiso sa storage at ulitin ang iyong aksyon. - Could not load Card Browser Appearance + HIndi mabuksan ang Card Browser Appearance - Failed to schedule reminders - Too many reminders scheduled. Some will not appear + Bigong makaskedyul ng mga paalala + Masyadong maraming paalalang nakaskedyul. May mga ibang hindi lalabas. - Set Language - Some multilingual keyboards, such as GBoard support changing language when editing text\n\nPlease request the “setImeHintLocales” feature from your keyboard manufacturer if your keyboard does not change language. + Pumili ng Wika + May mga multilingual na keyboard tulad ng GBoard na maaaring palitan ang wika habang nag-eedit ng teksto\n\nMangyaring magrequest ng \"setImeHintLocales\" na katangian mula sa gumawa ng iyong keyboard kung hindi nito sinusuporta ang pagpapalit ng wika. - Using AnkiDroid - AnkiDroid Manual - Anki Manual + Paggamit sa AnkiDroid + Patnubay sa AnkiDroid + Patnubay sa Anki AnkiDroid FAQ - Get Help + Humingi ng Tulong Mailing List Reddit - Report a Bug - Support AnkiDroid - Donate - Develop - Rate - Other - Translate - Community + I-sumbong ang Bug + Suportahan ang AnkiDroid + Maghandog + Mag-develop + I-rate + Iba pa + Isalin + Komunidad Anki Forums Discord Facebook Twitter - Privacy - AnkiDroid Privacy Policy - AnkiWeb Privacy Policy - AnkiWeb Terms and Conditions - Send troubleshooting report - Report already submitted - Report was sent! + Praybasi + Polisiya Pangpraybasi ng AnkiDroid + Polisiya Pangpraybasi ng AnkiWeb + Mga Termino at Kondisyon ng AnkiWeb + Magpadala ng ulat pang-ayos + Naipadala na ang ulat + Naipadala ang ulat! - An automatic sync may be triggered in %d second - An automatic sync may be triggered in %d seconds + Maaaring gumana ang automatic na pag-sync sa %d segundo + Maaaring gumana ang automatic na pag-sync sa %d segundo - Your internet provider may charge money for data use - Number of new cards to see today in this deck. - Number of cards due today in this deck. - Number of cards in learning in this deck. + Maaaring sumingil ang iyong internet provider sa paggamit ng data + Dami ng mga bagong card na makikita ngayong araw sa deck na ito. + Dami ng mga card na nakatakda ngayong araw sa deck na ito. + Dami ng mga card na pag-aaralan ngayong araw sa deck na ito. - Open the deck overview page containing the number of cards to see today. - Deck package (.apkg) - Collection package (.colpkg) + Buksan ang pahina ng buod ng deck na naglalaman ng dami ng mga card na makikita ngayong araw. + Deck na package (.apkg) + Koleksyon na package (.colpkg) Text file (.txt, .csv) - You cannot create a subdeck for all decks + Hindi ka maaaring lumikha ng subdeck para sa lahat ng mga deck. - Backup your collection - You haven\'t backed up your collection in a while. You should do this now to prevent data loss - Backup - Disable reminder - Later - Don\'t show again - Data loss warning - Due to Android privacy changes, your data and automated backups will be deleted from your phone if the app is uninstalled + I-backup ang iyong koleksyon + Matagal mo nang hindi nai-backup ang iyong koleksyon. Mangyaring gawin na ito ngayon nang maiwasan ang pagkawala ng datos. + I-backup + Tanggalin ang paalala + Mamaya + Huwag ipakita muli + Babala sa pagkawala ng datos + Dahil sa pagbabago ng praybasi ng Android, mabubura ang iyong datos at automated na backup sa iyong phone kapag inuninstall ang app. - Due to Android privacy changes, your data and automated backups will be inaccessible if the app is uninstalled + Dahil sa pagbabago ng praybasi ng Android, mabubura ang iyong datos at automated na backup sa iyong phone kapag inuninstall ang app. - Deck already exists - If you have deck ordering issues (e.g. ‘10’ appears before ‘2’), replace ‘2’ with ‘02’ + Umiiral na ang deck na ito + Kung may mga isyu ka sa hanay ng iyong deck (hal. lumabas ang \'10\' bago ang \'2\'), palitan ang \'2\' ng \'02\' - Set interval to same value + I-set ang pagitan sa parehong halaga - Show card in - Show cards in + Ipakita ang card makalipas ang + Ipakita ang mga card makalipas ang - Show card in range - Show cards in range + Ipakita ang card sa pagitan + Ipakita ang mga card sa pagitan - day - days + araw + araw - From - To + Mula + Hanggang diff --git a/AnkiDroid/src/main/res/values-fr/01-core.xml b/AnkiDroid/src/main/res/values-fr/01-core.xml index a9576b20c634..cadead758706 100644 --- a/AnkiDroid/src/main/res/values-fr/01-core.xml +++ b/AnkiDroid/src/main/res/values-fr/01-core.xml @@ -245,4 +245,6 @@ ou reconnecter le support amovible qui contient votre collection. Accès à tous les fichiers Schéma à remplir Supprimer le compte + + Instant card diff --git a/AnkiDroid/src/main/res/values-fy/01-core.xml b/AnkiDroid/src/main/res/values-fy/01-core.xml index b3aa87394cb3..f3896ea0e5cf 100644 --- a/AnkiDroid/src/main/res/values-fy/01-core.xml +++ b/AnkiDroid/src/main/res/values-fy/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-ga/01-core.xml b/AnkiDroid/src/main/res/values-ga/01-core.xml index 1f3fbe5d2117..ec572f4b5f17 100644 --- a/AnkiDroid/src/main/res/values-ga/01-core.xml +++ b/AnkiDroid/src/main/res/values-ga/01-core.xml @@ -264,4 +264,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-gl/01-core.xml b/AnkiDroid/src/main/res/values-gl/01-core.xml index fb8f5a841305..6f23480269c7 100644 --- a/AnkiDroid/src/main/res/values-gl/01-core.xml +++ b/AnkiDroid/src/main/res/values-gl/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-got/01-core.xml b/AnkiDroid/src/main/res/values-got/01-core.xml index 09a3645fcbd9..98ab3a7b758f 100644 --- a/AnkiDroid/src/main/res/values-got/01-core.xml +++ b/AnkiDroid/src/main/res/values-got/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-gu/01-core.xml b/AnkiDroid/src/main/res/values-gu/01-core.xml index 0635db17ff93..9193aeda8d18 100644 --- a/AnkiDroid/src/main/res/values-gu/01-core.xml +++ b/AnkiDroid/src/main/res/values-gu/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion એકાઉન્ટ દૂર કરો + + Instant card diff --git a/AnkiDroid/src/main/res/values-heb/01-core.xml b/AnkiDroid/src/main/res/values-heb/01-core.xml index 676cc5b5912c..09333bf0f5bf 100644 --- a/AnkiDroid/src/main/res/values-heb/01-core.xml +++ b/AnkiDroid/src/main/res/values-heb/01-core.xml @@ -256,4 +256,6 @@ גישה לכל הקבצים חסימת תמונה הסר חשבון + + Instant card diff --git a/AnkiDroid/src/main/res/values-hi/01-core.xml b/AnkiDroid/src/main/res/values-hi/01-core.xml index 7e01308d180e..16d91274de0c 100644 --- a/AnkiDroid/src/main/res/values-hi/01-core.xml +++ b/AnkiDroid/src/main/res/values-hi/01-core.xml @@ -249,4 +249,6 @@ Back - बैक सभी फ़ाइलों का एक्सेस छवि अवरोधन खाता हटाएं + + Instant card diff --git a/AnkiDroid/src/main/res/values-hr/01-core.xml b/AnkiDroid/src/main/res/values-hr/01-core.xml index e68ecad6a9b3..42994e42e884 100644 --- a/AnkiDroid/src/main/res/values-hr/01-core.xml +++ b/AnkiDroid/src/main/res/values-hr/01-core.xml @@ -252,4 +252,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-hu/01-core.xml b/AnkiDroid/src/main/res/values-hu/01-core.xml index 66ce047fea7d..4d781fa7ea6a 100644 --- a/AnkiDroid/src/main/res/values-hu/01-core.xml +++ b/AnkiDroid/src/main/res/values-hu/01-core.xml @@ -245,4 +245,6 @@ Hozzáférés minden fájlhoz Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-hy/01-core.xml b/AnkiDroid/src/main/res/values-hy/01-core.xml index 6e82d5b8f64b..8261e95db145 100644 --- a/AnkiDroid/src/main/res/values-hy/01-core.xml +++ b/AnkiDroid/src/main/res/values-hy/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-ind/01-core.xml b/AnkiDroid/src/main/res/values-ind/01-core.xml index 2f926ff9fc13..f886a20ae076 100644 --- a/AnkiDroid/src/main/res/values-ind/01-core.xml +++ b/AnkiDroid/src/main/res/values-ind/01-core.xml @@ -241,4 +241,6 @@ Akses semua berkas Oklusi Gambar Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-is/01-core.xml b/AnkiDroid/src/main/res/values-is/01-core.xml index 0ab660bb9a2b..8bc574242c05 100644 --- a/AnkiDroid/src/main/res/values-is/01-core.xml +++ b/AnkiDroid/src/main/res/values-is/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-it/01-core.xml b/AnkiDroid/src/main/res/values-it/01-core.xml index d5b29fb08e1b..25510604ce7d 100644 --- a/AnkiDroid/src/main/res/values-it/01-core.xml +++ b/AnkiDroid/src/main/res/values-it/01-core.xml @@ -246,4 +246,6 @@ Accesso a tutti i file Occludi immagine Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-iw/01-core.xml b/AnkiDroid/src/main/res/values-iw/01-core.xml index 676cc5b5912c..09333bf0f5bf 100644 --- a/AnkiDroid/src/main/res/values-iw/01-core.xml +++ b/AnkiDroid/src/main/res/values-iw/01-core.xml @@ -256,4 +256,6 @@ גישה לכל הקבצים חסימת תמונה הסר חשבון + + Instant card diff --git a/AnkiDroid/src/main/res/values-ja/01-core.xml b/AnkiDroid/src/main/res/values-ja/01-core.xml index 766f4a2b41cb..f0c56f65a7c6 100644 --- a/AnkiDroid/src/main/res/values-ja/01-core.xml +++ b/AnkiDroid/src/main/res/values-ja/01-core.xml @@ -240,4 +240,6 @@ すべてのファイルへのアクセス 画像穴埋め問題 アカウントを削除 + + Instant card diff --git a/AnkiDroid/src/main/res/values-jv/01-core.xml b/AnkiDroid/src/main/res/values-jv/01-core.xml index fb8f523620b3..14f075f1926f 100644 --- a/AnkiDroid/src/main/res/values-jv/01-core.xml +++ b/AnkiDroid/src/main/res/values-jv/01-core.xml @@ -240,4 +240,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-ka/01-core.xml b/AnkiDroid/src/main/res/values-ka/01-core.xml index 6bea94e22aae..557dcd630fcb 100644 --- a/AnkiDroid/src/main/res/values-ka/01-core.xml +++ b/AnkiDroid/src/main/res/values-ka/01-core.xml @@ -246,4 +246,6 @@ წვდომა ყველა ფაილზე სასურათე საფარველები Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-kk/01-core.xml b/AnkiDroid/src/main/res/values-kk/01-core.xml index 38bab93093ca..4d8415dff6d3 100644 --- a/AnkiDroid/src/main/res/values-kk/01-core.xml +++ b/AnkiDroid/src/main/res/values-kk/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-km/01-core.xml b/AnkiDroid/src/main/res/values-km/01-core.xml index 1b6379ed0b12..df732364aa1f 100644 --- a/AnkiDroid/src/main/res/values-km/01-core.xml +++ b/AnkiDroid/src/main/res/values-km/01-core.xml @@ -240,4 +240,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-kn/01-core.xml b/AnkiDroid/src/main/res/values-kn/01-core.xml index c0ac23f08cf8..fecc22b56040 100644 --- a/AnkiDroid/src/main/res/values-kn/01-core.xml +++ b/AnkiDroid/src/main/res/values-kn/01-core.xml @@ -242,4 +242,6 @@ ಎಲ್ಲಾ ಫೈಲ್‌ಗಳ ಪ್ರವೇಶ ಚಿತ್ರ ಮುಚ್ಚುವಿಕೆ ಖಾತೆಯನ್ನು ತೆಗೆದುಹಾಕಿ + + Instant card diff --git a/AnkiDroid/src/main/res/values-ko/01-core.xml b/AnkiDroid/src/main/res/values-ko/01-core.xml index 383c235af2a3..8e5b56a9a0e0 100644 --- a/AnkiDroid/src/main/res/values-ko/01-core.xml +++ b/AnkiDroid/src/main/res/values-ko/01-core.xml @@ -240,4 +240,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-ku/01-core.xml b/AnkiDroid/src/main/res/values-ku/01-core.xml index b152b1a63113..19afcac2b6a5 100644 --- a/AnkiDroid/src/main/res/values-ku/01-core.xml +++ b/AnkiDroid/src/main/res/values-ku/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-ky/01-core.xml b/AnkiDroid/src/main/res/values-ky/01-core.xml index 4c07b82cf530..d1a7f2f7f5da 100644 --- a/AnkiDroid/src/main/res/values-ky/01-core.xml +++ b/AnkiDroid/src/main/res/values-ky/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-lt/01-core.xml b/AnkiDroid/src/main/res/values-lt/01-core.xml index e09a5da0a955..41056d09e401 100644 --- a/AnkiDroid/src/main/res/values-lt/01-core.xml +++ b/AnkiDroid/src/main/res/values-lt/01-core.xml @@ -258,4 +258,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-lv/01-core.xml b/AnkiDroid/src/main/res/values-lv/01-core.xml index 0ac4ab2cba33..b10afa98472b 100644 --- a/AnkiDroid/src/main/res/values-lv/01-core.xml +++ b/AnkiDroid/src/main/res/values-lv/01-core.xml @@ -252,4 +252,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-mk/01-core.xml b/AnkiDroid/src/main/res/values-mk/01-core.xml index 0bb14951627c..5b9b7a4543c3 100644 --- a/AnkiDroid/src/main/res/values-mk/01-core.xml +++ b/AnkiDroid/src/main/res/values-mk/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-ml/01-core.xml b/AnkiDroid/src/main/res/values-ml/01-core.xml index fedaf8fa8e07..bfa89fddab0a 100644 --- a/AnkiDroid/src/main/res/values-ml/01-core.xml +++ b/AnkiDroid/src/main/res/values-ml/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-mn/01-core.xml b/AnkiDroid/src/main/res/values-mn/01-core.xml index dc6ada989a8f..aa4b81831c5e 100644 --- a/AnkiDroid/src/main/res/values-mn/01-core.xml +++ b/AnkiDroid/src/main/res/values-mn/01-core.xml @@ -245,4 +245,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-mr/01-core.xml b/AnkiDroid/src/main/res/values-mr/01-core.xml index ef61bdf4db85..4bbe3ecd9c39 100644 --- a/AnkiDroid/src/main/res/values-mr/01-core.xml +++ b/AnkiDroid/src/main/res/values-mr/01-core.xml @@ -246,4 +246,6 @@ सर्व फायली प्रवेश Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-ms/01-core.xml b/AnkiDroid/src/main/res/values-ms/01-core.xml index e637323c375d..c7b92101fef9 100644 --- a/AnkiDroid/src/main/res/values-ms/01-core.xml +++ b/AnkiDroid/src/main/res/values-ms/01-core.xml @@ -240,4 +240,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-my/01-core.xml b/AnkiDroid/src/main/res/values-my/01-core.xml index 49a5394612b0..ee3de2211143 100644 --- a/AnkiDroid/src/main/res/values-my/01-core.xml +++ b/AnkiDroid/src/main/res/values-my/01-core.xml @@ -245,4 +245,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-nl/01-core.xml b/AnkiDroid/src/main/res/values-nl/01-core.xml index 59784640fa22..56cc917ed62a 100644 --- a/AnkiDroid/src/main/res/values-nl/01-core.xml +++ b/AnkiDroid/src/main/res/values-nl/01-core.xml @@ -245,4 +245,6 @@ Toegang tot alle bestanden Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-nn/01-core.xml b/AnkiDroid/src/main/res/values-nn/01-core.xml index d1ef99ca11a3..2007f7999933 100644 --- a/AnkiDroid/src/main/res/values-nn/01-core.xml +++ b/AnkiDroid/src/main/res/values-nn/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-no/01-core.xml b/AnkiDroid/src/main/res/values-no/01-core.xml index 2827089034b3..3a16b27bf405 100644 --- a/AnkiDroid/src/main/res/values-no/01-core.xml +++ b/AnkiDroid/src/main/res/values-no/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-or/01-core.xml b/AnkiDroid/src/main/res/values-or/01-core.xml index e91257767c30..7d0283397a5a 100644 --- a/AnkiDroid/src/main/res/values-or/01-core.xml +++ b/AnkiDroid/src/main/res/values-or/01-core.xml @@ -246,4 +246,6 @@ ସମସ୍ତ ଫାଇଲ୍ ପ୍ରବେଶାଧିକାର ପ୍ରତିଛବି ଅନ୍ତର୍ଦ୍ଧାନ Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-pa/01-core.xml b/AnkiDroid/src/main/res/values-pa/01-core.xml index fd8884622fee..42a6bfd7b151 100644 --- a/AnkiDroid/src/main/res/values-pa/01-core.xml +++ b/AnkiDroid/src/main/res/values-pa/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-pl/01-core.xml b/AnkiDroid/src/main/res/values-pl/01-core.xml index dae88d55dbc7..4276053427b9 100644 --- a/AnkiDroid/src/main/res/values-pl/01-core.xml +++ b/AnkiDroid/src/main/res/values-pl/01-core.xml @@ -258,4 +258,6 @@ Dostęp do wszystkich plików Image Occlusion Usuń konto + + Instant card diff --git a/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml b/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml index e978917ed41b..69a9f28c2e94 100644 --- a/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml +++ b/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml @@ -246,4 +246,6 @@ Acesso a todos os arquivos Oclusão de imagem Remover conta + + Instant card diff --git a/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml b/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml index b41deceed400..620df44d834d 100644 --- a/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml +++ b/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml @@ -246,4 +246,6 @@ Acesso a todos os ficheiros Oclusão de imagem Eliminar conta + + Instant card diff --git a/AnkiDroid/src/main/res/values-ro/01-core.xml b/AnkiDroid/src/main/res/values-ro/01-core.xml index 679a89173797..facd74d98a44 100644 --- a/AnkiDroid/src/main/res/values-ro/01-core.xml +++ b/AnkiDroid/src/main/res/values-ro/01-core.xml @@ -252,4 +252,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-ru/01-core.xml b/AnkiDroid/src/main/res/values-ru/01-core.xml index ad22d60a6ec3..f6b535381cfd 100644 --- a/AnkiDroid/src/main/res/values-ru/01-core.xml +++ b/AnkiDroid/src/main/res/values-ru/01-core.xml @@ -256,4 +256,6 @@ Доступ ко всем файлам Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-sat/01-core.xml b/AnkiDroid/src/main/res/values-sat/01-core.xml index 3ed69aaec64a..2f3df5414d9d 100644 --- a/AnkiDroid/src/main/res/values-sat/01-core.xml +++ b/AnkiDroid/src/main/res/values-sat/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-sc/01-core.xml b/AnkiDroid/src/main/res/values-sc/01-core.xml index ec205fe22733..b68cb291e53e 100644 --- a/AnkiDroid/src/main/res/values-sc/01-core.xml +++ b/AnkiDroid/src/main/res/values-sc/01-core.xml @@ -250,4 +250,6 @@ Atzessu a totu sos archìvios Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-sk/01-core.xml b/AnkiDroid/src/main/res/values-sk/01-core.xml index 3fa695e4ceab..117df5f3665b 100644 --- a/AnkiDroid/src/main/res/values-sk/01-core.xml +++ b/AnkiDroid/src/main/res/values-sk/01-core.xml @@ -258,4 +258,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-sl/01-core.xml b/AnkiDroid/src/main/res/values-sl/01-core.xml index 114daafac024..8c882d3c6da3 100644 --- a/AnkiDroid/src/main/res/values-sl/01-core.xml +++ b/AnkiDroid/src/main/res/values-sl/01-core.xml @@ -258,4 +258,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-sq/01-core.xml b/AnkiDroid/src/main/res/values-sq/01-core.xml index fa0700c15e7f..bf0af94a58a3 100644 --- a/AnkiDroid/src/main/res/values-sq/01-core.xml +++ b/AnkiDroid/src/main/res/values-sq/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-sr/01-core.xml b/AnkiDroid/src/main/res/values-sr/01-core.xml index 236d4de5658a..8234db214d16 100644 --- a/AnkiDroid/src/main/res/values-sr/01-core.xml +++ b/AnkiDroid/src/main/res/values-sr/01-core.xml @@ -252,4 +252,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-ss/01-core.xml b/AnkiDroid/src/main/res/values-ss/01-core.xml index 8235179ea6a9..2a0dd54cb663 100644 --- a/AnkiDroid/src/main/res/values-ss/01-core.xml +++ b/AnkiDroid/src/main/res/values-ss/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-sv/01-core.xml b/AnkiDroid/src/main/res/values-sv/01-core.xml index ab7d638a633c..61888602e5c9 100644 --- a/AnkiDroid/src/main/res/values-sv/01-core.xml +++ b/AnkiDroid/src/main/res/values-sv/01-core.xml @@ -245,4 +245,6 @@ Åtkomst till alla filer Bildövertäckning Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-sw/01-core.xml b/AnkiDroid/src/main/res/values-sw/01-core.xml index 8235179ea6a9..2a0dd54cb663 100644 --- a/AnkiDroid/src/main/res/values-sw/01-core.xml +++ b/AnkiDroid/src/main/res/values-sw/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-ta/01-core.xml b/AnkiDroid/src/main/res/values-ta/01-core.xml index 088ea59d51cb..b5a354a0f450 100644 --- a/AnkiDroid/src/main/res/values-ta/01-core.xml +++ b/AnkiDroid/src/main/res/values-ta/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-te/01-core.xml b/AnkiDroid/src/main/res/values-te/01-core.xml index 61e682c1582b..5ebec6b6e747 100644 --- a/AnkiDroid/src/main/res/values-te/01-core.xml +++ b/AnkiDroid/src/main/res/values-te/01-core.xml @@ -242,4 +242,6 @@ అన్ని ఫైల్‌ల యాక్సెస్ చిత్రం ముగింపు ఖాతాను తీసివేయండి + + Instant card diff --git a/AnkiDroid/src/main/res/values-tg/01-core.xml b/AnkiDroid/src/main/res/values-tg/01-core.xml index 01d93aa095d6..9d4321d6c35e 100644 --- a/AnkiDroid/src/main/res/values-tg/01-core.xml +++ b/AnkiDroid/src/main/res/values-tg/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-tgl/01-core.xml b/AnkiDroid/src/main/res/values-tgl/01-core.xml index b92c5f2037ed..4f52602d93ad 100644 --- a/AnkiDroid/src/main/res/values-tgl/01-core.xml +++ b/AnkiDroid/src/main/res/values-tgl/01-core.xml @@ -250,4 +250,6 @@ Burahin ang “%2$s” uri ng baraha, at ang %1$d mga baraha? All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-th/01-core.xml b/AnkiDroid/src/main/res/values-th/01-core.xml index 913d586af4ac..4c758383eaa1 100644 --- a/AnkiDroid/src/main/res/values-th/01-core.xml +++ b/AnkiDroid/src/main/res/values-th/01-core.xml @@ -240,4 +240,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-ti/01-core.xml b/AnkiDroid/src/main/res/values-ti/01-core.xml index 5e3dcdb301d0..ffd5a919dcc2 100644 --- a/AnkiDroid/src/main/res/values-ti/01-core.xml +++ b/AnkiDroid/src/main/res/values-ti/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-tn/01-core.xml b/AnkiDroid/src/main/res/values-tn/01-core.xml index 8235179ea6a9..2a0dd54cb663 100644 --- a/AnkiDroid/src/main/res/values-tn/01-core.xml +++ b/AnkiDroid/src/main/res/values-tn/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-tr/01-core.xml b/AnkiDroid/src/main/res/values-tr/01-core.xml index 83b65d5cd982..d95e415e4ee9 100644 --- a/AnkiDroid/src/main/res/values-tr/01-core.xml +++ b/AnkiDroid/src/main/res/values-tr/01-core.xml @@ -246,4 +246,6 @@ Bütün dosyalara erişim Resim Örtüsü Hesabı sil + + Instant card diff --git a/AnkiDroid/src/main/res/values-ts/01-core.xml b/AnkiDroid/src/main/res/values-ts/01-core.xml index 8235179ea6a9..2a0dd54cb663 100644 --- a/AnkiDroid/src/main/res/values-ts/01-core.xml +++ b/AnkiDroid/src/main/res/values-ts/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-tt/01-core.xml b/AnkiDroid/src/main/res/values-tt/01-core.xml index 704b759cc750..6d8b076a2391 100644 --- a/AnkiDroid/src/main/res/values-tt/01-core.xml +++ b/AnkiDroid/src/main/res/values-tt/01-core.xml @@ -240,4 +240,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-uk/01-core.xml b/AnkiDroid/src/main/res/values-uk/01-core.xml index 9affb1546945..cb74739dedd4 100644 --- a/AnkiDroid/src/main/res/values-uk/01-core.xml +++ b/AnkiDroid/src/main/res/values-uk/01-core.xml @@ -257,4 +257,6 @@ Доступ до всіх файлів Оклюзія зображення Видалити обліковий запис + + Instant card diff --git a/AnkiDroid/src/main/res/values-ur/01-core.xml b/AnkiDroid/src/main/res/values-ur/01-core.xml index 94910fb5efe6..b828877a7b48 100644 --- a/AnkiDroid/src/main/res/values-ur/01-core.xml +++ b/AnkiDroid/src/main/res/values-ur/01-core.xml @@ -242,4 +242,6 @@ تمام فائلوں تک رسائی Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-uz/01-core.xml b/AnkiDroid/src/main/res/values-uz/01-core.xml index eac04fb5892c..b92b47184c5e 100644 --- a/AnkiDroid/src/main/res/values-uz/01-core.xml +++ b/AnkiDroid/src/main/res/values-uz/01-core.xml @@ -247,4 +247,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-ve/01-core.xml b/AnkiDroid/src/main/res/values-ve/01-core.xml index 8235179ea6a9..2a0dd54cb663 100644 --- a/AnkiDroid/src/main/res/values-ve/01-core.xml +++ b/AnkiDroid/src/main/res/values-ve/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-vi/01-core.xml b/AnkiDroid/src/main/res/values-vi/01-core.xml index c39fb71b8400..6dc2d895eb64 100644 --- a/AnkiDroid/src/main/res/values-vi/01-core.xml +++ b/AnkiDroid/src/main/res/values-vi/01-core.xml @@ -240,4 +240,6 @@ Quyền truy cập vào mọi tệp Image Occlusion Gỡ bỏ tài khoản + + Instant card diff --git a/AnkiDroid/src/main/res/values-wo/01-core.xml b/AnkiDroid/src/main/res/values-wo/01-core.xml index c694c922e747..0b47452e37c2 100644 --- a/AnkiDroid/src/main/res/values-wo/01-core.xml +++ b/AnkiDroid/src/main/res/values-wo/01-core.xml @@ -240,4 +240,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-xh/01-core.xml b/AnkiDroid/src/main/res/values-xh/01-core.xml index 8235179ea6a9..2a0dd54cb663 100644 --- a/AnkiDroid/src/main/res/values-xh/01-core.xml +++ b/AnkiDroid/src/main/res/values-xh/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-yue/01-core.xml b/AnkiDroid/src/main/res/values-yue/01-core.xml index fad6f795548f..324d945c5ebc 100644 --- a/AnkiDroid/src/main/res/values-yue/01-core.xml +++ b/AnkiDroid/src/main/res/values-yue/01-core.xml @@ -240,4 +240,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml b/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml index 7af5b563e9e0..70b7d31a2b59 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml @@ -240,4 +240,6 @@ 所有文件访问权限 图片遮挡 删除账户 + + Instant card diff --git a/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml b/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml index 5b706136f70b..8e816bfaaafc 100644 --- a/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml +++ b/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml @@ -237,4 +237,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/AnkiDroid/src/main/res/values-zu/01-core.xml b/AnkiDroid/src/main/res/values-zu/01-core.xml index 8235179ea6a9..2a0dd54cb663 100644 --- a/AnkiDroid/src/main/res/values-zu/01-core.xml +++ b/AnkiDroid/src/main/res/values-zu/01-core.xml @@ -246,4 +246,6 @@ All files access Image Occlusion Remove account + + Instant card diff --git a/docs/marketing/localized_description/ankidroid-titles.txt b/docs/marketing/localized_description/ankidroid-titles.txt index 6e206184c101..a17ca617d905 100644 --- a/docs/marketing/localized_description/ankidroid-titles.txt +++ b/docs/marketing/localized_description/ankidroid-titles.txt @@ -1,9 +1,9 @@ AnkiDroid Flashcards af: AnkiDroid Flitskaarte ar: البطاقات التعليميةآنكيدرويد +az: AnkiDroid Flaş Kartları be: Карткі для запамінання AnkiDroid bg: AnkiDroid Флашкарти -az: AnkiDroid Flaş Kartları ca: AnkiDroid fitxes per memoritzar cs: AnkiDroid kartičky de: AnkiDroid Karteikarten From 701b5582de43fa0742ddf8964034ed5bce82c274 Mon Sep 17 00:00:00 2001 From: Robozinho <65715921+RobozinhoD@users.noreply.github.com> Date: Sat, 4 May 2024 06:13:13 -0300 Subject: [PATCH 022/138] remove chromeos release files --- .github/workflows/label.yml | 1 - .../ankidroid-titles.txt | 44 -------------- .../ichi2/anki/lint/rules/TranslationTypo.kt | 2 +- tools/chromeos/release.sh | 57 ------------------- tools/localization/src/constants.ts | 1 - tools/localization/src/update.ts | 15 ----- 6 files changed, 1 insertion(+), 119 deletions(-) delete mode 100644 docs/marketing/localized_description/ankidroid-titles.txt delete mode 100755 tools/chromeos/release.sh diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml index beb5f214ddca..e63a7b53d60d 100644 --- a/.github/workflows/label.yml +++ b/.github/workflows/label.yml @@ -98,7 +98,6 @@ jobs: "18-standard-models", "20-search-preference", "marketdescription", - "ankidroid-titles", ]; let stringsLabel = "Strings"; diff --git a/docs/marketing/localized_description/ankidroid-titles.txt b/docs/marketing/localized_description/ankidroid-titles.txt deleted file mode 100644 index a17ca617d905..000000000000 --- a/docs/marketing/localized_description/ankidroid-titles.txt +++ /dev/null @@ -1,44 +0,0 @@ -AnkiDroid Flashcards -af: AnkiDroid Flitskaarte -ar: البطاقات التعليميةآنكيدرويد -az: AnkiDroid Flaş Kartları -be: Карткі для запамінання AnkiDroid -bg: AnkiDroid Флашкарти -ca: AnkiDroid fitxes per memoritzar -cs: AnkiDroid kartičky -de: AnkiDroid Karteikarten -eo: AnkiDroid -es-AR: Tarjetas flash AnkiDroid -es-ES: Tarjetas AnkiDroid -et: AnkiDroid mälukaardid -fa: فلش کارتهای انکی دروید -fi: AnkiDroid-muistikortit -fr: AnkiDroid (Cartes mémoire) -fy-NL: AnkiDroid flitskaarten -gl: Cartóns AnkiDroid -he: קלפי לימוד של AnkiDroid -he: קלפי לימוד של AnkiDroid -hi: AnkiDroid फ़्लैशकार्ड -hu: AnkiDroid Szókártyák -hy-AM: AnkiDroid քարտեր -id: Kartu Flash AnkiDroid -ka: AnkiDroid: სამეცადინო ბარათები -kk: AnkiDroid жаттау карталары -ko: AnkiDroid 플래시 카드 -lt: „AnkiDroid“ atminties kortelės -mr: अंकीड्रोएड फ़्लँशकार्डस् -ms: Kad Imbasan AnkiDroid -nl: AnkiDroid flitskaarten -pl: AnkiDroid – Fiszki -ru: AnkiDroid: карточки для запоминания -sc: Cartas mnemònicas de AnkiDroid -sk: AnkiDroid kartičky -sl: Pomnilne kartice AnkiDroid -sr: AnkiDroid флеш-картице -sv-SE: AnkiDroid Flashkort -th: บัตรคำ AnkiDroid -tr: AnkiDroid Bilgi Kartları -ur-PK: آنکی ڈیرائڈ فلیشکارڈز -vi: Thẻ thông minh AnkiDroid -zh-CN: AnkiDroid 记忆卡片 -zh-TW: AnkiDroid 單字卡 \ No newline at end of file diff --git a/lint-rules/src/main/java/com/ichi2/anki/lint/rules/TranslationTypo.kt b/lint-rules/src/main/java/com/ichi2/anki/lint/rules/TranslationTypo.kt index 50dfb7cee097..272a01bb1dc5 100644 --- a/lint-rules/src/main/java/com/ichi2/anki/lint/rules/TranslationTypo.kt +++ b/lint-rules/src/main/java/com/ichi2/anki/lint/rules/TranslationTypo.kt @@ -50,7 +50,7 @@ class TranslationTypo : ResourceXmlDetector(), XmlScanner { ) // copied from tools/localization/src/constants.ts - // excludes ankidroid-titles and marketdescription as these are .txt + // excludes marketdescription as it is .txt private val I18N_FILES = listOf( "01-core", "02-strings", diff --git a/tools/chromeos/release.sh b/tools/chromeos/release.sh deleted file mode 100755 index 2756d1542f77..000000000000 --- a/tools/chromeos/release.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env bash - -# Check if jq exists -command -v jq >/dev/null 2>&1 || { echo >&2 "This script requires jq (http://stedolan.github.io/jq/) but it's not installed. Aborting."; exit 1; } - -# Check opts -if [ $# -eq 0 ]; then - echo "missing path to apk_to_crx.py conversion script (get it from https://console.developers.google.com/storage/browser/arc-sdk/ for the current stable version of Chrome)" - exit 1 -elif [ $# -eq 1 ]; then - echo "missing path to apk file" - exit 1 -fi - -SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -SOURCE_PATH=${SCRIPT_PATH%/*/*} - -# Make sure cws directory exists -mkdir -p cws - -# Use --for-webstore instead of --unpacked to remove potential debug stuff -python2 $1 --metadata $SCRIPT_PATH/release.crx.json --for-webstore --output cws/build.zip --destructive $2 - -# Unzip CWS package -rm -rf cws/unpacked -unzip -q cws/build.zip -d cws/unpacked -rm cws/build.zip - -# Optimize image for CWS -cp $SOURCE_PATH/docs/marketing/chrome-web-store/icon.png cws/unpacked/ - -# Add short name and description placeholder to manifest -echo "`jq '.short_name = "AnkiDroid" | .description = "__MSG_extDesc__"' cws/unpacked/manifest.json`" > cws/unpacked/manifest.json - -# Extract name and description from ankidroid-titles.txt and marketdescription-XY.txt and -# inject them into extName and extDesc of messages.json in _locales/XY -LANGS=`ls cws/unpacked/_locales` -DEFAULT_NAME='AnkiDroid Flashcards' -DEFAULT_DESC='Memorize anything with AnkiDroid!' -for LANG in $LANGS -do - if [ -f $SOURCE_PATH/docs/marketing/localized_description/marketdescription-$LANG.txt ] - then - NAME=`grep "^$LANG:" $SOURCE_PATH/docs/marketing/localized_description/ankidroid-titles.txt | sed 's/.*\: //'` - DESC=`head -n 1 $SOURCE_PATH/docs/marketing/localized_description/marketdescription-$LANG.txt` - echo "`jq '.extName.message = $extName | .extDesc.message = $extDesc' --arg extName "${NAME:-DEFAULT_NAME}" --arg extDesc "${DESC-DEFAULT_DESC}" cws/unpacked/_locales/$LANG/messages.json`" > cws/unpacked/_locales/$LANG/messages.json - else - echo "`jq '.extName.message = $extName | .extDesc.message = $extDesc' --arg extName "$DEFAULT_NAME" --arg extDesc "$DEFAULT_DESC" cws/unpacked/_locales/$LANG/messages.json`" > cws/unpacked/_locales/$LANG/messages.json - fi -done - -# Work around intent filter restriction to support APKG file handler -echo "`jq 'del(.file_handlers.any.types) | .file_handlers.any.extensions = ["apkg"]' cws/unpacked/manifest.json`" > cws/unpacked/manifest.json - -# Prepare release package -cd cws/unpacked -zip -q -r -o ../../cws/release.zip * diff --git a/tools/localization/src/constants.ts b/tools/localization/src/constants.ts index cb792a296d6b..dfeeb56740d1 100644 --- a/tools/localization/src/constants.ts +++ b/tools/localization/src/constants.ts @@ -32,7 +32,6 @@ createDirIfNotExisting(TEMP_DIR); export const I18N_FILES_DIR = path.join(__dirname, RES_DIR, "values/"); export const RES_VALUES_LANG_DIR = path.join(__dirname, RES_DIR, "values-"); -export const TITLE_FILE = path.join(__dirname, DOCS_MARKET_DIR, "ankidroid-titles.txt"); export const MARKET_DESC_FILE = path.join( __dirname, DOCS_MARKET_DIR, diff --git a/tools/localization/src/update.ts b/tools/localization/src/update.ts index 11ee96383bb2..cd1b42687f21 100644 --- a/tools/localization/src/update.ts +++ b/tools/localization/src/update.ts @@ -20,7 +20,6 @@ import { LOCALIZED_REGIONS, TEMP_DIR, TITLE_STR, - TITLE_FILE, I18N_FILES, XML_LICENSE_HEADER, RES_VALUES_LANG_DIR, @@ -142,16 +141,6 @@ async function update( return true; } - // these are appended to a special file - if (f == "15-markettitle") { - const translatedTitle = translatedContent.split("\n")[0]; - - if (TITLE_STR != translatedTitle) { - fs.appendFileSync(TITLE_FILE, "\n" + language + ": " + translatedTitle); - } - return true; - } - // Everything else is a regular file to translate into Android resources const newfile = valuesDirectory + f + ".xml"; fs.writeFileSync(newfile, translatedContent); @@ -162,10 +151,6 @@ async function update( * Update translated I18n files in res/value dir */ export async function updateI18nFiles() { - // Create new / empty marketing title file to populate - fs.truncateSync(TITLE_FILE); - fs.appendFileSync(TITLE_FILE, TITLE_STR); - for (const language of LANGUAGES) { // Language tags are 2- or 3-letters, and regional files need a marker in Android where subtag starts with "r" // Note the documentation does not describe what works in practice: From b903a1fd246007468a26faea2bde8e9448d517b9 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Fri, 31 May 2024 16:15:16 +0100 Subject: [PATCH 023/138] test(card-browser-view-model): handle manualInit Due to threading with Robolectric, ignoreValuesFromViewModelLaunch was not handled in the same way that it would in a real class (config was updated, even though it should be unchanged) This fixes the issue inside `runViewModelTest` --- .../com/ichi2/anki/browser/CardBrowserViewModel.kt | 14 ++++++++++++-- .../ichi2/anki/browser/CardBrowserViewModelTest.kt | 9 +++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index 3c80a97a1af2..327bf4adbbb5 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -88,7 +88,8 @@ class CardBrowserViewModel( private val lastDeckIdRepository: LastDeckIdRepository, private val cacheDir: File, options: CardBrowserLaunchOptions?, - preferences: SharedPreferencesProvider + preferences: SharedPreferencesProvider, + private val manualInit: Boolean = false ) : ViewModel(), SharedPreferencesProvider by preferences { // Set by the UI to determine the number of cards to preload before returning search results @@ -306,10 +307,19 @@ class CardBrowserViewModel( reverseDirectionFlow.update { ReverseDirection.fromConfig(config) } } Timber.i("initCompleted") - flowOfInitCompleted.update { true } + + if (!manualInit) { + flowOfInitCompleted.update { true } + } } } + @VisibleForTesting + fun manualInit() { + require(manualInit) { "'manualInit' should be true" } + flowOfInitCompleted.update { true } + } + /** Whether any rows are selected */ fun hasSelectedAnyRows(): Boolean = selectedRows.isNotEmpty() diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index 537db48a422e..6984034e7623 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -206,7 +206,7 @@ class CardBrowserViewModelTest : JvmTest() { } } - private fun runViewModelTest(notes: Int = 0, testBody: suspend CardBrowserViewModel.() -> Unit) = runTest { + private fun runViewModelTest(notes: Int = 0, manualInit: Boolean = true, testBody: suspend CardBrowserViewModel.() -> Unit) = runTest { for (i in 0 until notes) { addNoteUsingBasicModel() } @@ -214,8 +214,13 @@ class CardBrowserViewModelTest : JvmTest() { lastDeckIdRepository = SharedPreferencesLastDeckIdRepository(), cacheDir = createTransientDirectory(), options = null, - preferences = AnkiDroidApp.sharedPreferencesProvider + preferences = AnkiDroidApp.sharedPreferencesProvider, + manualInit = manualInit ) + // makes ignoreValuesFromViewModelLaunch work under test + if (manualInit) { + viewModel.manualInit() + } testBody(viewModel) } From 0acdba3359076036e8dc8890e8f537eaeebf67c8 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Fri, 31 May 2024 16:20:12 +0100 Subject: [PATCH 024/138] fix(card-browser): incorrect 'notes' sort order Issue: when moving to 'cards or notes' We used 'sortType' instead of 'noteSortType' Then when we loaded it from the collection, it caused problems Caused: ``` com.ichi2.libanki.exception.InvalidSearchException: net.ankiweb.rsdroid.exceptions.BackendInvalidInputException: Can't sort Notes by Custom. at com.ichi2.libanki.Collection.findNotes(Collection.kt:398) ``` Fixes 16514 --- .../com/ichi2/anki/browser/CardBrowserViewModel.kt | 2 +- .../src/main/java/com/ichi2/anki/model/SortType.kt | 7 +++++-- .../ichi2/anki/browser/CardBrowserViewModelTest.kt | 11 +++++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index 327bf4adbbb5..6d75e5082cad 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -303,7 +303,7 @@ class CardBrowserViewModel( flowOfCardsOrNotes.update { cardsOrNotes } withCol { - sortTypeFlow.update { SortType.fromCol(config, sharedPrefs()) } + sortTypeFlow.update { SortType.fromCol(config, cardsOrNotes, sharedPrefs()) } reverseDirectionFlow.update { ReverseDirection.fromConfig(config) } } Timber.i("initCompleted") diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/model/SortType.kt b/AnkiDroid/src/main/java/com/ichi2/anki/model/SortType.kt index d0ed0d27b70d..eb3af13a3b18 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/model/SortType.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/model/SortType.kt @@ -55,6 +55,8 @@ enum class SortType(val ankiSortType: String?, val cardBrowserLabelIndex: Int) { config.set("sortType", this.ankiSortType ?: SORT_FIELD.ankiSortType) config.set("noteSortType", this.ankiSortType ?: SORT_FIELD.ankiSortType) preferences.edit { + // TODO: This should be changed to use the collection + // and have a different value for cards & notes putBoolean("cardBrowserNoSorting", this@SortType == NO_SORTING) } } @@ -64,8 +66,9 @@ enum class SortType(val ankiSortType: String?, val cardBrowserLabelIndex: Int) { if (this == NO_SORTING) SortOrder.NoOrdering() else SortOrder.UseCollectionOrdering() companion object { - fun fromCol(config: Config, preferences: SharedPreferences): SortType { - val colOrder = config.get("sortType") + fun fromCol(config: Config, cardsOrNotes: CardsOrNotes, preferences: SharedPreferences): SortType { + val configKey = if (cardsOrNotes == CardsOrNotes.CARDS) "sortType" else "noteSortType" + val colOrder = config.get(configKey) val type = entries.firstOrNull { it.ankiSortType == colOrder } ?: NO_SORTING if (type == SORT_FIELD && preferences.getBoolean("cardBrowserNoSorting", false)) { return NO_SORTING diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index 6984034e7623..9da27e231e4d 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -206,6 +206,17 @@ class CardBrowserViewModelTest : JvmTest() { } } + @Test + fun `sort order from notes is selected - 16514`() { + col.config.set("sortType", "noteCrt") + col.config.set("noteSortType", "_field_Frequency") + with(col) { CardsOrNotes.NOTES.saveToCollection() } + + runViewModelTest(notes = 1) { + assertThat("1 row returned", rowCount, equalTo(1)) + } + } + private fun runViewModelTest(notes: Int = 0, manualInit: Boolean = true, testBody: suspend CardBrowserViewModel.() -> Unit) = runTest { for (i in 0 until notes) { addNoteUsingBasicModel() From ee1dcd8571a439bf3bf9a4597b9172f30a9aefb4 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Mon, 27 May 2024 00:37:26 +0100 Subject: [PATCH 025/138] test(card-browser-view-model): selected rows This also introduces Turbine, a Google-recommended library for testing flows https://github.com/cashapp/turbine https://developer.android.com/kotlin/flow/test Accessed 2024-05-27 --- AnkiDroid/build.gradle | 2 ++ .../anki/browser/CardBrowserViewModelTest.kt | 32 +++++++++++++++++++ gradle/libs.versions.toml | 2 ++ 3 files changed, 36 insertions(+) diff --git a/AnkiDroid/build.gradle b/AnkiDroid/build.gradle index db7f0a297b84..0a6e1a174c1c 100644 --- a/AnkiDroid/build.gradle +++ b/AnkiDroid/build.gradle @@ -402,6 +402,8 @@ dependencies { exclude module: "protobuf-lite" } testImplementation libs.androidx.work.testing + // for testing flows + testImplementation libs.cashapp.turbine androidTestImplementation project(':testlib') diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index 9da27e231e4d..483add38c5f9 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -17,6 +17,7 @@ package com.ichi2.anki.browser import androidx.test.ext.junit.runners.AndroidJUnit4 +import app.cash.turbine.test import com.ichi2.anki.AnkiDroidApp import com.ichi2.anki.CardBrowser import com.ichi2.anki.CollectionManager @@ -217,6 +218,37 @@ class CardBrowserViewModelTest : JvmTest() { } } + fun `selected rows are refreshed`() = runViewModelTest(notes = 2) { + flowOfSelectedRows.test { + // initially, flowOfSelectedRows should not have emitted anything + expectNoEvents() + + selectAll() + assertThat("initial selection", awaitItem().size, equalTo(2)) + + selectNone() + assertThat("deselected all", awaitItem().size, equalTo(0)) + + toggleRowSelectionAtPosition(0) + assertThat("selected row", awaitItem().size, equalTo(1)) + + toggleRowSelectionAtPosition(0) + assertThat("deselected rows", awaitItem().size, equalTo(0)) + + selectRowAtPosition(0) + assertThat("select rows explicitly", awaitItem().size, equalTo(1)) + + selectRowAtPosition(0) + expectNoEvents() + + selectRowsBetweenPositions(0, 1) + assertThat("select rows between positions", awaitItem().size, equalTo(2)) + + selectRowsBetweenPositions(0, 1) + expectNoEvents() + } + } + private fun runViewModelTest(notes: Int = 0, manualInit: Boolean = true, testBody: suspend CardBrowserViewModel.() -> Unit) = runTest { for (i in 0 until notes) { addNoteUsingBasicModel() diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 05d9890ea10b..44b191042df5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -67,6 +67,7 @@ sharedPreferencesMock = "1.2.4" slf4jTimber = "3.1" timber = "5.0.1" triplet = "3.9.1" +turbine = "1.1.0" workRuntimeKtx = "2.9.0" [libraries] @@ -151,6 +152,7 @@ mockito-inline = { module = "org.mockito:mockito-inline", version.ref = "mockito mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", version.ref = "mockitoKotlin" } mockk = { module = "io.mockk:mockk", version.ref = "mockk" } robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" } +cashapp-turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" } [plugins] From f688c1ce74fd6bf5e1b973c343538ccaa09b0c47 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Mon, 27 May 2024 14:22:10 +0100 Subject: [PATCH 026/138] test(card-browser-view-model): selected ids selected card and note ids To improve coverage --- .../anki/browser/CardBrowserViewModelTest.kt | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index 483add38c5f9..bcf707436728 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -38,6 +38,7 @@ import com.ichi2.testutils.createTransientDirectory import com.ichi2.testutils.mockIt import kotlinx.coroutines.flow.first import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.containsInAnyOrder import org.hamcrest.Matchers.equalTo import org.hamcrest.Matchers.nullValue import org.junit.Test @@ -249,6 +250,30 @@ class CardBrowserViewModelTest : JvmTest() { } } + @Test + fun `selected card and note ids`() { + val notes = List(2) { addNoteUsingBasicAndReversedModel() } + + val nids = notes.map { it.id }.toTypedArray() + val cids = notes.flatMap { it.cids() }.toTypedArray() + + runViewModelTest { + setCardsOrNotes(CardsOrNotes.CARDS).join() + selectAll() + assertThat("cards: rowCount", rowCount, equalTo(4)) + assertThat("cards: cids", queryAllSelectedCardIds(), containsInAnyOrder(*cids)) + assertThat("cards: nids", queryAllSelectedNoteIds(), containsInAnyOrder(*nids)) + + selectNone() + + setCardsOrNotes(CardsOrNotes.NOTES).join() + selectAll() + assertThat("notes: rowCount", rowCount, equalTo(2)) + assertThat("notes: cids", queryAllSelectedCardIds(), containsInAnyOrder(*cids)) + assertThat("notes: nids", queryAllSelectedNoteIds(), containsInAnyOrder(*nids)) + } + } + private fun runViewModelTest(notes: Int = 0, manualInit: Boolean = true, testBody: suspend CardBrowserViewModel.() -> Unit) = runTest { for (i in 0 until notes) { addNoteUsingBasicModel() From dbd9cbcd6e3700fc09a70a77d45a957b45a0ac00 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Mon, 27 May 2024 16:05:50 +0100 Subject: [PATCH 027/138] fix(card-browser-view-model): column indices * do not update config on init --- .../com/ichi2/anki/browser/CardBrowserViewModel.kt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index 6d75e5082cad..9327c5a1cb5d 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -82,6 +82,7 @@ import kotlin.math.max import kotlin.math.min @NeedsTest("reverseDirectionFlow/sortTypeFlow are not updated on .launch { }") +@NeedsTest("columIndex1/2 config is not not updated on init") @NeedsTest("13442: selected deck is not changed, as this affects the reviewer") @NeedsTest("search is called after launch()") class CardBrowserViewModel( @@ -274,11 +275,19 @@ class CardBrowserViewModel( } flowOfColumnIndex1 - .onEach { index -> sharedPrefs().edit { putInt(DISPLAY_COLUMN_1_KEY, index) } } + .ignoreValuesFromViewModelLaunch() + .onEach { index -> + Timber.d("updating %s", DISPLAY_COLUMN_1_KEY) + sharedPrefs().edit { putInt(DISPLAY_COLUMN_1_KEY, index) } + } .launchIn(viewModelScope) flowOfColumnIndex2 - .onEach { index -> sharedPrefs().edit { putInt(DISPLAY_COLUMN_2_KEY, index) } } + .ignoreValuesFromViewModelLaunch() + .onEach { index -> + Timber.d("updating %s", DISPLAY_COLUMN_2_KEY) + sharedPrefs().edit { putInt(DISPLAY_COLUMN_2_KEY, index) } + } .launchIn(viewModelScope) performSearchFlow.onEach { From 8d04cc69db774721d3da2cd52b1bac567a6c20dd Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Mon, 27 May 2024 16:06:20 +0100 Subject: [PATCH 028/138] tests(card-browser-view-model): column indices Add tests: * changing column index 1 * changing column index 2 This does not handle checking for config changes on init To improve coverage --- .../anki/browser/CardBrowserViewModelTest.kt | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index bcf707436728..4aacefb84e8f 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -17,6 +17,7 @@ package com.ichi2.anki.browser import androidx.test.ext.junit.runners.AndroidJUnit4 +import app.cash.turbine.TurbineTestContext import app.cash.turbine.test import com.ichi2.anki.AnkiDroidApp import com.ichi2.anki.CardBrowser @@ -274,6 +275,42 @@ class CardBrowserViewModelTest : JvmTest() { } } + @Test + fun `changing column index 1`() = runViewModelTest { + flowOfColumnIndex1.test { + ignoreEventsDuringViewModelInit() + + assertThat("default column1Index value", column1Index, equalTo(0)) + + setColumn1Index(1) + + assertThat("flowOfColumnIndex1", awaitItem(), equalTo(1)) + assertThat("column1Index", column1Index, equalTo(1)) + + // expect no change if the value is selected again + setColumn1Index(1) + expectNoEvents() + } + } + + @Test + fun `changing column index 2`() = runViewModelTest { + flowOfColumnIndex2.test { + ignoreEventsDuringViewModelInit() + + assertThat("default column2Index value", column2Index, equalTo(0)) + + setColumn2Index(1) + + assertThat("flowOfColumnIndex2", awaitItem(), equalTo(1)) + assertThat("column2Index", column2Index, equalTo(1)) + + // expect no change if the value is selected again + setColumn2Index(1) + expectNoEvents() + } + } + private fun runViewModelTest(notes: Int = 0, manualInit: Boolean = true, testBody: suspend CardBrowserViewModel.() -> Unit) = runTest { for (i in 0 until notes) { addNoteUsingBasicModel() @@ -322,6 +359,21 @@ private fun CardBrowserViewModel.selectRowsWithPositions(vararg positions: Int) } } +/** + * Helper for testing flows: + * + * A MutableStateFlow can either emit a value or not emit a value + * depending on whether a consumer subscribes before or after the task launched + * from init is completed + */ +private fun TurbineTestContext.ignoreEventsDuringViewModelInit() { + try { + expectMostRecentItem() + } catch (e: AssertionError) { + // explicitly ignored: no items + } +} + private suspend fun CardBrowserViewModel.waitForSearchResults() { searchJob?.join() } From a2a109caa87ccfd84d9f49ae3294749712961ac2 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Sun, 2 Jun 2024 02:52:20 +0000 Subject: [PATCH 029/138] Bumped version to 2.19alpha4 --- AnkiDroid/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AnkiDroid/build.gradle b/AnkiDroid/build.gradle index 0a6e1a174c1c..3d27a9144c06 100644 --- a/AnkiDroid/build.gradle +++ b/AnkiDroid/build.gradle @@ -74,8 +74,8 @@ android { // // This ensures the correct ordering between the various types of releases (dev < alpha < beta < release) which is // needed for upgrades to be offered correctly. - versionCode=21900103 - versionName="2.19alpha3" + versionCode=21900104 + versionName="2.19alpha4" minSdk 23 // also in testlib/build.gradle.kts // After #13695: change .tests_emulator.yml targetSdk 33 // also in [api|testlib]/build.gradle.kts and ../robolectricDownloader.gradle From f8784da930c53c6262df6b24bf6dd4727d504b24 Mon Sep 17 00:00:00 2001 From: Ashish Yadav <48384865+criticalay@users.noreply.github.com> Date: Wed, 1 May 2024 00:05:21 +0530 Subject: [PATCH 030/138] feat: Display custom flag names Anki's 'Browse' allows a user to rename flags Support displaying these custom names not setting them Fixes 16204 --- .../main/java/com/ichi2/anki/CardBrowser.kt | 127 ++++++------------ .../src/main/java/com/ichi2/anki/Flag.kt | 45 ++++++- .../src/main/java/com/ichi2/anki/Reviewer.kt | 69 ++++------ .../ichi2/anki/previewer/PreviewerFragment.kt | 39 +++--- .../com/ichi2/anki/utils/ext/JSONObject.kt | 29 ++++ .../src/main/java/com/ichi2/libanki/Config.kt | 12 ++ AnkiDroid/src/main/res/menu/card_browser.xml | 32 +---- .../res/menu/card_browser_multiselect.xml | 32 +---- AnkiDroid/src/main/res/menu/previewer.xml | 32 +---- AnkiDroid/src/main/res/menu/reviewer.xml | 32 +---- 10 files changed, 170 insertions(+), 279 deletions(-) create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/utils/ext/JSONObject.kt diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt index 7a7cbf0d0fd7..3ebf48f87349 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt @@ -723,7 +723,10 @@ open class CardBrowser : // restore drawer click listener and icon restoreDrawerIcon() menuInflater.inflate(R.menu.card_browser, menu) - setFlagTitles(menu) + menu.findItem(R.id.action_search_by_flag).subMenu?.let { + subMenu -> + setupFlags(subMenu, Mode.SINGLE_SELECT) + } saveSearchItem = menu.findItem(R.id.action_save_search) saveSearchItem?.isVisible = false // the searchview's query always starts empty. mySearchesItem = menu.findItem(R.id.action_list_my_searches) @@ -777,7 +780,10 @@ open class CardBrowser : } else { // multi-select mode menuInflater.inflate(R.menu.card_browser_multiselect, menu) - setMultiSelectFlagTitles(menu) + menu.findItem(R.id.action_flag).subMenu?.let { + subMenu -> + setupFlags(subMenu, Mode.MULTI_SELECT) + } showBackIcon() increaseHorizontalPaddingOfOverflowMenuIcons(menu) } @@ -795,6 +801,28 @@ open class CardBrowser : return super.onCreateOptionsMenu(menu) } + /** + * Representing different selection modes. + */ + enum class Mode(val value: Int) { + SINGLE_SELECT(1000), + MULTI_SELECT(1001) + } + + private fun setupFlags(subMenu: SubMenu, mode: Mode) { + lifecycleScope.launch { + val groupId = when (mode) { + Mode.SINGLE_SELECT -> mode.value + Mode.MULTI_SELECT -> mode.value + } + + for ((flag, displayName) in Flag.queryDisplayNames()) { + subMenu.add(groupId, flag.ordinal, Menu.NONE, displayName) + .setIcon(flag.drawableRes) + } + } + } + override fun onNavigationPressed() { if (viewModel.isInMultiSelectMode) { viewModel.endMultiSelectMode() @@ -803,28 +831,6 @@ open class CardBrowser : } } - private fun setFlagTitles(menu: Menu) { - menu.findItem(R.id.action_select_flag_zero).title = Flag.NONE.displayName() - menu.findItem(R.id.action_select_flag_one).title = Flag.RED.displayName() - menu.findItem(R.id.action_select_flag_two).title = Flag.ORANGE.displayName() - menu.findItem(R.id.action_select_flag_three).title = Flag.GREEN.displayName() - menu.findItem(R.id.action_select_flag_four).title = Flag.BLUE.displayName() - menu.findItem(R.id.action_select_flag_five).title = Flag.PINK.displayName() - menu.findItem(R.id.action_select_flag_six).title = Flag.TURQUOISE.displayName() - menu.findItem(R.id.action_select_flag_seven).title = Flag.PURPLE.displayName() - } - - private fun setMultiSelectFlagTitles(menu: Menu) { - menu.findItem(R.id.action_flag_zero).title = Flag.NONE.displayName() - menu.findItem(R.id.action_flag_one).title = Flag.RED.displayName() - menu.findItem(R.id.action_flag_two).title = Flag.ORANGE.displayName() - menu.findItem(R.id.action_flag_three).title = Flag.GREEN.displayName() - menu.findItem(R.id.action_flag_four).title = Flag.BLUE.displayName() - menu.findItem(R.id.action_flag_five).title = Flag.PINK.displayName() - menu.findItem(R.id.action_flag_six).title = Flag.TURQUOISE.displayName() - menu.findItem(R.id.action_flag_seven).title = Flag.PURPLE.displayName() - } - private fun updatePreviewMenuItem() { previewItem?.isVisible = viewModel.rowCount > 0 } @@ -931,6 +937,15 @@ open class CardBrowser : undoSnackbar != null && undoSnackbar!!.isShown -> undoSnackbar!!.dismiss() } + Flag.entries.find { it.ordinal == item.itemId }?.let { flag -> + when (item.groupId) { + Mode.SINGLE_SELECT.value -> filterByFlag(flag) + Mode.MULTI_SELECT.value -> updateFlagForSelectedRows(flag) + else -> return@let + } + return true + } + when (item.itemId) { android.R.id.home -> { viewModel.endMultiSelectMode() @@ -993,70 +1008,6 @@ open class CardBrowser : showFilterByTagsDialog() return true } - R.id.action_flag_zero -> { - updateFlagForSelectedRows(Flag.NONE) - return true - } - R.id.action_flag_one -> { - updateFlagForSelectedRows(Flag.RED) - return true - } - R.id.action_flag_two -> { - updateFlagForSelectedRows(Flag.ORANGE) - return true - } - R.id.action_flag_three -> { - updateFlagForSelectedRows(Flag.GREEN) - return true - } - R.id.action_flag_four -> { - updateFlagForSelectedRows(Flag.BLUE) - return true - } - R.id.action_flag_five -> { - updateFlagForSelectedRows(Flag.PINK) - return true - } - R.id.action_flag_six -> { - updateFlagForSelectedRows(Flag.TURQUOISE) - return true - } - R.id.action_flag_seven -> { - updateFlagForSelectedRows(Flag.PURPLE) - return true - } - R.id.action_select_flag_zero -> { - filterByFlag(Flag.NONE) - return true - } - R.id.action_select_flag_one -> { - filterByFlag(Flag.RED) - return true - } - R.id.action_select_flag_two -> { - filterByFlag(Flag.ORANGE) - return true - } - R.id.action_select_flag_three -> { - filterByFlag(Flag.GREEN) - return true - } - R.id.action_select_flag_four -> { - filterByFlag(Flag.BLUE) - return true - } - R.id.action_select_flag_five -> { - filterByFlag(Flag.PINK) - return true - } - R.id.action_select_flag_six -> { - filterByFlag(Flag.TURQUOISE) - return true - } - R.id.action_select_flag_seven -> { - filterByFlag(Flag.PURPLE) - return true - } R.id.action_delete_card -> { deleteSelectedNotes() return true diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt b/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt index 22dac034004d..503baf3ee4a3 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt @@ -18,9 +18,12 @@ package com.ichi2.anki import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import com.ichi2.anki.CollectionManager.TR +import com.ichi2.anki.CollectionManager.withCol +import com.ichi2.anki.utils.ext.getStringOrNull import com.ichi2.libanki.Card import com.ichi2.libanki.CardId import com.ichi2.libanki.Collection +import org.json.JSONObject enum class Flag(val code: Int, @DrawableRes val drawableRes: Int, @ColorRes val browserColorRes: Int?) { NONE(0, R.drawable.ic_flag_transparent, null), @@ -32,7 +35,18 @@ enum class Flag(val code: Int, @DrawableRes val drawableRes: Int, @ColorRes val TURQUOISE(6, R.drawable.ic_flag_turquoise, R.color.flag_turquoise), PURPLE(7, R.drawable.ic_flag_purple, R.color.flag_purple); - fun displayName(): String = when (this) { + /** + * Retrieves the name associated with the flag. This may be user-defined + * + * @see queryDisplayNames - more efficient + */ + private fun displayName(labels: FlagLabels): String { + // NONE may not be renamed + if (this == NONE) return defaultDisplayName() + return labels.getLabel(this) ?: defaultDisplayName() + } + + private fun defaultDisplayName(): String = when (this) { NONE -> TR.browsingNoFlag() RED -> TR.actionsFlagRed() ORANGE -> TR.actionsFlagOrange() @@ -47,7 +61,36 @@ enum class Flag(val code: Int, @DrawableRes val drawableRes: Int, @ColorRes val fun fromCode(code: Int): Flag { return entries.first { it.code == code } } + + /** + * @return A mapping from each [Flag] to its display name (optionally user-defined) + */ + suspend fun queryDisplayNames(): Map { + // load user-defined flag labels from the collection + val labels = FlagLabels.loadFromColConfig() + // either map to user-provided name, or translated name + return Flag.entries.associateWith { it.displayName(labels) } + } } } + +/** + * User-defined labels for flags. Stored in the collection optionally as `{ "1": "Redd" }` + * [Flag.NONE] does not have a label + */ +@JvmInline +private value class FlagLabels(val value: JSONObject) { + /** + * @return the user-defined label for the provided flag, or null if undefined + * This is not supported for [Flag.NONE] and is validated outside this method + */ + fun getLabel(flag: Flag): String? = value.getStringOrNull(flag.code.toString()) + + companion object { + suspend fun loadFromColConfig() = + FlagLabels(withCol { config.getObject("flagLabels", JSONObject()) }) + } +} + fun Collection.setUserFlag(flag: Flag, cids: List) = this.setUserFlag(flag.code, cids) fun Card.setUserFlag(flag: Flag) = this.setUserFlag(flag.code) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt b/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt index 771a4983a2c6..8719b2e979c3 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt @@ -40,12 +40,12 @@ import androidx.appcompat.view.menu.MenuBuilder import androidx.appcompat.widget.Toolbar import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat +import androidx.lifecycle.lifecycleScope import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat import anki.frontend.SetSchedulingStatesRequest import com.google.android.material.color.MaterialColors import com.google.android.material.snackbar.Snackbar import com.ichi2.anim.ActivityTransitionAnimation.getInverseTransition -import com.ichi2.anki.CollectionManager.TR import com.ichi2.anki.CollectionManager.withCol import com.ichi2.anki.Whiteboard.Companion.createInstance import com.ichi2.anki.Whiteboard.OnPaintColorChangeListener @@ -89,6 +89,7 @@ import com.ichi2.utils.HandlerUtils.getDefaultLooper import com.ichi2.utils.Permissions.canRecordAudio import com.ichi2.utils.ViewGroupUtils.setRenderWorkaround import com.ichi2.widget.WidgetStatus.updateInBackground +import kotlinx.coroutines.launch import timber.log.Timber import java.io.File @@ -169,6 +170,8 @@ open class Reviewer : FlashCardViewerResultCallback() ) + private val flagItemIds = mutableSetOf() + override fun onCreate(savedInstanceState: Bundle?) { if (showedActivityFailedScreen(savedInstanceState)) { return @@ -353,6 +356,13 @@ open class Reviewer : if (drawerToggle.onOptionsItemSelected(item)) { return true } + + Flag.entries.find { it.ordinal == item.itemId }?.let { flag -> + Timber.i("Reviewer:: onOptionItemSelected Flag - ${flag.name} clicked") + onFlag(currentCard, flag) + return true + } + when (item.itemId) { android.R.id.home -> { Timber.i("Reviewer:: Home button pressed") @@ -452,38 +462,6 @@ open class Reviewer : Timber.i("Reviewer:: Add note button pressed") addNote() } - R.id.action_flag_zero -> { - Timber.i("Reviewer:: No flag") - onFlag(currentCard, Flag.NONE) - } - R.id.action_flag_one -> { - Timber.i("Reviewer:: Flag one") - onFlag(currentCard, Flag.RED) - } - R.id.action_flag_two -> { - Timber.i("Reviewer:: Flag two") - onFlag(currentCard, Flag.ORANGE) - } - R.id.action_flag_three -> { - Timber.i("Reviewer:: Flag three") - onFlag(currentCard, Flag.GREEN) - } - R.id.action_flag_four -> { - Timber.i("Reviewer:: Flag four") - onFlag(currentCard, Flag.BLUE) - } - R.id.action_flag_five -> { - Timber.i("Reviewer:: Flag five") - onFlag(currentCard, Flag.PINK) - } - R.id.action_flag_six -> { - Timber.i("Reviewer:: Flag six") - onFlag(currentCard, Flag.TURQUOISE) - } - R.id.action_flag_seven -> { - Timber.i("Reviewer:: Flag seven") - onFlag(currentCard, Flag.PURPLE) - } R.id.action_card_info -> { Timber.i("Card Viewer:: Card Info") openCardInfo() @@ -692,7 +670,7 @@ open class Reviewer : Timber.d("onCreateOptionsMenu()") // NOTE: This is called every time a new question is shown via invalidate options menu menuInflater.inflate(R.menu.reviewer, menu) - setFlagTitles(menu) + menu.findItem(R.id.action_flag).subMenu?.let { subMenu -> setupFlags(subMenu) } displayIcons(menu) actionButtons.setCustomButtonsStatus(menu) val alpha = Themes.ALPHA_ICON_ENABLED_LIGHT @@ -844,20 +822,19 @@ open class Reviewer : onboarding.onCreate() increaseHorizontalPaddingOfOverflowMenuIcons(menu) - tintOverflowMenuIcons(menu, skipIf = { isFlagResource(it.itemId) }) + tintOverflowMenuIcons(menu, skipIf = { isFlagItem(it) }) return super.onCreateOptionsMenu(menu) } - private fun setFlagTitles(menu: Menu) { - menu.findItem(R.id.action_flag_zero).title = Flag.NONE.displayName() - menu.findItem(R.id.action_flag_one).title = Flag.RED.displayName() - menu.findItem(R.id.action_flag_two).title = Flag.ORANGE.displayName() - menu.findItem(R.id.action_flag_three).title = Flag.GREEN.displayName() - menu.findItem(R.id.action_flag_four).title = Flag.BLUE.displayName() - menu.findItem(R.id.action_flag_five).title = Flag.PINK.displayName() - menu.findItem(R.id.action_flag_six).title = Flag.TURQUOISE.displayName() - menu.findItem(R.id.action_flag_seven).title = Flag.PURPLE.displayName() + private fun setupFlags(subMenu: SubMenu) { + lifecycleScope.launch { + for ((flag, displayName) in Flag.queryDisplayNames()) { + val menuItem = subMenu.add(Menu.NONE, flag.ordinal, Menu.NONE, displayName) + .setIcon(flag.drawableRes) + flagItemIds.add(menuItem.itemId) + } + } } @SuppressLint("RestrictedApi") @@ -873,8 +850,8 @@ open class Reviewer : } } - private fun isFlagResource(itemId: Int): Boolean { - return itemId == R.id.action_flag_seven || itemId == R.id.action_flag_six || itemId == R.id.action_flag_five || itemId == R.id.action_flag_four || itemId == R.id.action_flag_three || itemId == R.id.action_flag_two || itemId == R.id.action_flag_one + private fun isFlagItem(menuItem: MenuItem): Boolean { + return flagItemIds.contains(menuItem.itemId) } override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerFragment.kt index a1bf9534ea2d..b5567e279e06 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerFragment.kt @@ -50,6 +50,7 @@ import com.ichi2.annotations.NeedsTest import com.ichi2.utils.performClickIfEnabled import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch +import timber.log.Timber class PreviewerFragment : CardViewerFragment(R.layout.previewer), @@ -97,7 +98,7 @@ class PreviewerFragment : } /* ************************************* Menu items ************************************* */ val menu = view.findViewById(R.id.toolbar).menu - setFlagTitles(menu) + setupFlagMenu(menu) lifecycleScope.launch { viewModel.backSideOnly @@ -123,6 +124,7 @@ class PreviewerFragment : } } + // handle selection of a new flag lifecycleScope.launch { viewModel.flagCode .flowWithLifecycle(lifecycle) @@ -188,34 +190,31 @@ class PreviewerFragment : } } + private fun setupFlagMenu(menu: Menu) { + val submenu = menu.findItem(R.id.action_flag).subMenu + lifecycleScope.launch { + for ((flag, name) in Flag.queryDisplayNames()) { + submenu?.add(Menu.NONE, flag.ordinal, Menu.NONE, name) + ?.setIcon(flag.drawableRes) + } + } + } + override fun onMenuItemClick(item: MenuItem): Boolean { + Flag.entries.find { it.ordinal == item.itemId }?.let { flag -> + Timber.i("PreviewerFragment:: onMenuItemClick Flag - ${flag.name} clicked") + viewModel.setFlag(flag) + return true + } + when (item.itemId) { R.id.action_edit -> editCard() R.id.action_mark -> viewModel.toggleMark() R.id.action_back_side_only -> viewModel.toggleBackSideOnly() - R.id.action_flag_zero -> viewModel.setFlag(Flag.NONE) - R.id.action_flag_one -> viewModel.setFlag(Flag.RED) - R.id.action_flag_two -> viewModel.setFlag(Flag.ORANGE) - R.id.action_flag_three -> viewModel.setFlag(Flag.GREEN) - R.id.action_flag_four -> viewModel.setFlag(Flag.BLUE) - R.id.action_flag_five -> viewModel.setFlag(Flag.PINK) - R.id.action_flag_six -> viewModel.setFlag(Flag.TURQUOISE) - R.id.action_flag_seven -> viewModel.setFlag(Flag.PURPLE) } return true } - private fun setFlagTitles(menu: Menu) { - menu.findItem(R.id.action_flag_zero).title = Flag.NONE.displayName() - menu.findItem(R.id.action_flag_one).title = Flag.RED.displayName() - menu.findItem(R.id.action_flag_two).title = Flag.ORANGE.displayName() - menu.findItem(R.id.action_flag_three).title = Flag.GREEN.displayName() - menu.findItem(R.id.action_flag_four).title = Flag.BLUE.displayName() - menu.findItem(R.id.action_flag_five).title = Flag.PINK.displayName() - menu.findItem(R.id.action_flag_six).title = Flag.TURQUOISE.displayName() - menu.findItem(R.id.action_flag_seven).title = Flag.PURPLE.displayName() - } - private fun setBackSideOnlyButtonIcon(menu: Menu, isBackSideOnly: Boolean) { menu.findItem(R.id.action_back_side_only).apply { if (isBackSideOnly) { diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/utils/ext/JSONObject.kt b/AnkiDroid/src/main/java/com/ichi2/anki/utils/ext/JSONObject.kt new file mode 100644 index 000000000000..561f3c1cf10a --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/anki/utils/ext/JSONObject.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 Ashish Yadav + * + * 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 . + */ + +package com.ichi2.anki.utils.ext + +import org.json.JSONObject + +fun JSONObject.getStringOrNull(key: String): String? { + if (!has(key)) return null + return try { + getString(key) + } catch (_: Exception) { + null + } +} diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/Config.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/Config.kt index ae110942988b..4181ec535bb3 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/Config.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/Config.kt @@ -25,6 +25,7 @@ import kotlinx.serialization.json.Json import net.ankiweb.rsdroid.Backend import net.ankiweb.rsdroid.exceptions.BackendNotFoundException import org.json.JSONArray +import org.json.JSONException import org.json.JSONObject class Config(val backend: Backend) { @@ -69,4 +70,15 @@ class Config(val backend: Backend) { null } } + + @NotInLibAnki + fun getObject(key: String, default: JSONObject): JSONObject { + return try { + JSONObject(backend.getConfigJson(key).toStringUtf8()) + } catch (ex: BackendNotFoundException) { + default + } catch (ex: JSONException) { + default + } + } } diff --git a/AnkiDroid/src/main/res/menu/card_browser.xml b/AnkiDroid/src/main/res/menu/card_browser.xml index 2481fbcaf0e8..750f60a2993c 100644 --- a/AnkiDroid/src/main/res/menu/card_browser.xml +++ b/AnkiDroid/src/main/res/menu/card_browser.xml @@ -39,37 +39,7 @@ android:id="@+id/action_search_by_flag" android:title="@string/card_browser_search_by_flag"> - - - - - - - - + diff --git a/AnkiDroid/src/main/res/menu/card_browser_multiselect.xml b/AnkiDroid/src/main/res/menu/card_browser_multiselect.xml index 64deb37a7150..7d7248a6575d 100644 --- a/AnkiDroid/src/main/res/menu/card_browser_multiselect.xml +++ b/AnkiDroid/src/main/res/menu/card_browser_multiselect.xml @@ -25,37 +25,7 @@ android:title="@string/menu_flag_card" android:icon="@drawable/ic_flag_transparent"> - - - - - - - - + diff --git a/AnkiDroid/src/main/res/menu/previewer.xml b/AnkiDroid/src/main/res/menu/previewer.xml index 1c53b71283d6..4794fcb22eed 100644 --- a/AnkiDroid/src/main/res/menu/previewer.xml +++ b/AnkiDroid/src/main/res/menu/previewer.xml @@ -28,37 +28,7 @@ android:icon="@drawable/ic_flag_transparent" app:showAsAction="always" > - - - - - - - - + - - - - - - - - + Date: Sun, 2 Jun 2024 08:45:05 +0100 Subject: [PATCH 031/138] test(card-browser-view-model): sort order --- .../anki/browser/CardBrowserViewModelTest.kt | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index 4aacefb84e8f..ae3182c408e3 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -29,6 +29,9 @@ import com.ichi2.anki.browser.CardBrowserLaunchOptions.DeepLink import com.ichi2.anki.browser.CardBrowserLaunchOptions.SystemContextMenu import com.ichi2.anki.flagCardForNote import com.ichi2.anki.model.CardsOrNotes +import com.ichi2.anki.model.SortType.EASE +import com.ichi2.anki.model.SortType.NO_SORTING +import com.ichi2.anki.model.SortType.SORT_FIELD import com.ichi2.anki.setFlagFilterSync import com.ichi2.libanki.Consts.QUEUE_TYPE_MANUALLY_BURIED import com.ichi2.libanki.Consts.QUEUE_TYPE_NEW @@ -311,6 +314,52 @@ class CardBrowserViewModelTest : JvmTest() { } } + @Test + fun `change card order to NO_SORTING is a no-op if done twice`() = runViewModelTest { + flowOfSearchState.test { + ignoreEventsDuringViewModelInit() + assertThat("initial order", order, equalTo(SORT_FIELD)) + assertThat("initial direction", !orderAsc) + + // changing the order performs a search & changes order + changeCardOrder(NO_SORTING) + expectMostRecentItem() + assertThat("order changed", order, equalTo(NO_SORTING)) + assertThat("changed direction", !orderAsc) + + waitForSearchResults() + + // pressing 'no sorting' again is a no-op + changeCardOrder(NO_SORTING) + expectNoEvents() + assertThat("order unchanged", order, equalTo(NO_SORTING)) + assertThat("unchanged direction", !orderAsc) + } + } + + @Test + fun `change direction of results`() = runViewModelTest { + flowOfSearchState.test { + ignoreEventsDuringViewModelInit() + assertThat("initial order", order, equalTo(SORT_FIELD)) + assertThat("initial direction", !orderAsc) + + // changing the order performs a search & changes order + changeCardOrder(EASE) + expectMostRecentItem() + assertThat("order changed", order, equalTo(EASE)) + assertThat("changed direction is the default", !orderAsc) + + waitForSearchResults() + + // pressing 'ease' again changes direction + changeCardOrder(EASE) + expectMostRecentItem() + assertThat("order unchanged", order, equalTo(EASE)) + assertThat("direction is changed", orderAsc) + } + } + private fun runViewModelTest(notes: Int = 0, manualInit: Boolean = true, testBody: suspend CardBrowserViewModel.() -> Unit) = runTest { for (i in 0 until notes) { addNoteUsingBasicModel() From f0578c4b0b58e6315d953ffe73b3e5427bebffaf Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Sun, 2 Jun 2024 09:18:23 +0100 Subject: [PATCH 032/138] chore(card-browser): refactor 'suspendCards' * rename to toggleSuspendCards * Add method description * launch in viewModelScope --- .../main/java/com/ichi2/anki/CardBrowser.kt | 4 ++-- .../anki/browser/CardBrowserViewModel.kt | 22 +++++++++++++------ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt index 3ebf48f87349..75191406ad11 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt @@ -1017,7 +1017,7 @@ open class CardBrowser : return true } R.id.action_suspend_card -> { - suspendCards() + toggleSuspendCards() return true } R.id.action_toggle_bury -> { @@ -1522,7 +1522,7 @@ open class CardBrowser : updateList() } - private fun suspendCards() = launchCatchingTask { withProgress { viewModel.suspendCards() } } + private fun toggleSuspendCards() = launchCatchingTask { withProgress { viewModel.toggleSuspendCards().join() } } /** @see CardBrowserViewModel.toggleBury */ private fun toggleBury() = launchCatchingTask { diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index 9327c5a1cb5d..2216f1a92962 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -23,6 +23,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewmodel.initializer import androidx.lifecycle.viewmodel.viewModelFactory +import anki.collection.OpChanges import anki.collection.OpChangesWithCount import com.ichi2.anki.AnkiDroidApp import com.ichi2.anki.CardBrowser @@ -43,6 +44,7 @@ import com.ichi2.anki.setUserFlag import com.ichi2.annotations.NeedsTest import com.ichi2.libanki.Card import com.ichi2.libanki.CardId +import com.ichi2.libanki.ChangeManager import com.ichi2.libanki.Consts import com.ichi2.libanki.Consts.QUEUE_TYPE_MANUALLY_BURIED import com.ichi2.libanki.Consts.QUEUE_TYPE_SIBLING_BURIED @@ -77,7 +79,6 @@ import java.io.File import java.io.FileInputStream import java.io.FileOutputStream import java.util.Collections -import java.util.HashMap import kotlin.math.max import kotlin.math.min @@ -457,16 +458,23 @@ class CardBrowserViewModel( fun setColumn1Index(value: Int) = flowOfColumnIndex1.update { value } fun setColumn2Index(value: Int) = flowOfColumnIndex2.update { value } - suspend fun suspendCards() { + + /** + * Toggles the 'suspend' state of the selected cards + * + * If all cards are suspended, unsuspend all + * If no cards are suspended, suspend all + * If there is a mix, suspend all + * + * Changes are handled by [ChangeManager] + */ + fun toggleSuspendCards() = viewModelScope.launch { if (!hasSelectedAnyRows()) { - return + return@launch } val cardIds = queryAllSelectedCardIds() - undoableOp { - // if all cards are suspended, unsuspend all - // if no cards are suspended, suspend all - // if there is a mix, suspend all + undoableOp { val wantUnsuspend = cardIds.all { getCard(it).queue == Consts.QUEUE_TYPE_SUSPENDED } if (wantUnsuspend) { sched.unsuspendCards(cardIds) From c848579ba73831b0b70a7792375427efe0edcb08 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Sun, 2 Jun 2024 10:16:28 +0100 Subject: [PATCH 033/138] test(card-browser-view-model): suspend --- .../java/com/ichi2/libanki/ChangeManager.kt | 2 +- .../anki/browser/CardBrowserViewModelTest.kt | 176 +++++++++++++++++- .../ichi2/testutils/TestChangeSubscriber.kt | 51 +++++ 3 files changed, 227 insertions(+), 2 deletions(-) create mode 100644 AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/ChangeManager.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/ChangeManager.kt index bc8af178421f..7fd1b1dc3e49 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/ChangeManager.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/ChangeManager.kt @@ -42,7 +42,7 @@ import java.lang.ref.WeakReference import java.util.concurrent.CopyOnWriteArrayList object ChangeManager { - interface Subscriber { + fun interface Subscriber { /** * Called after a backend method invoked via col.op() or col.opWithProgress() * has modified the collection. Subscriber should inspect the changes, and update diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index ae3182c408e3..1d010a9ccecc 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -35,15 +35,22 @@ import com.ichi2.anki.model.SortType.SORT_FIELD import com.ichi2.anki.setFlagFilterSync import com.ichi2.libanki.Consts.QUEUE_TYPE_MANUALLY_BURIED import com.ichi2.libanki.Consts.QUEUE_TYPE_NEW +import com.ichi2.libanki.Consts.QUEUE_TYPE_SUSPENDED import com.ichi2.libanki.DeckId +import com.ichi2.libanki.Note import com.ichi2.testutils.IntentAssert import com.ichi2.testutils.JvmTest +import com.ichi2.testutils.TestClass import com.ichi2.testutils.createTransientDirectory +import com.ichi2.testutils.ensureNoOpsExecuted +import com.ichi2.testutils.ensureOpsExecuted import com.ichi2.testutils.mockIt import kotlinx.coroutines.flow.first import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.containsInAnyOrder import org.hamcrest.Matchers.equalTo +import org.hamcrest.Matchers.lessThan +import org.hamcrest.Matchers.not import org.hamcrest.Matchers.nullValue import org.junit.Test import org.junit.runner.RunWith @@ -360,7 +367,133 @@ class CardBrowserViewModelTest : JvmTest() { } } - private fun runViewModelTest(notes: Int = 0, manualInit: Boolean = true, testBody: suspend CardBrowserViewModel.() -> Unit) = runTest { + /* + * Note: suspension behavior has been questioned from a performance perspective and is + * subject to change + * + * Needing to know the 'suspended' status of all cards, makes this O(n). + * Anki uses the O(1) approach of using the first selected card + */ + + @Test + fun `suspend cards - cards - no selection`() = runViewModelTest(notes = 2) { + ensureNoOpsExecuted { + toggleSuspendCards() + + assertAllUnsuspended("no selection") + } + } + + @Test + fun `suspend - cards - all suspended`() = runViewModelTest(notes = 2) { + suspendAll() + ensureOpsExecuted(1) { + selectAll() + toggleSuspendCards() + + assertAllUnsuspended("all suspended: unsuspend") + } + } + + @Test + fun `suspend - cards - some suspended`() = runViewModelTest(notes = 2) { + suspend(cards.first()) + ensureOpsExecuted(1) { + selectAll() + toggleSuspendCards() + + assertAllSuspended("mixed selection: suspend all") + } + } + + @Test + fun `suspend - cards - none suspended`() = runViewModelTest(notes = 2) { + ensureOpsExecuted(1) { + selectAll() + toggleSuspendCards() + + assertAllSuspended("none suspended: suspend all") + } + } + + @Test + fun `suspend - notes - no selection`() = runViewModelNotesTest(notes = 2) { + ensureNoOpsExecuted { + toggleSuspendCards() + assertAllUnsuspended("none selected: do nothing") + } + } + + @Test + fun `suspend - notes - all suspended`() = runViewModelNotesTest(notes = 2) { + suspendAll() + ensureOpsExecuted(1) { + selectAll() + toggleSuspendCards() + assertAllUnsuspended("all suspended -> unsuspend") + } + } + + @Test + fun `suspend - notes - some notes suspended`() = runViewModelNotesTest(notes = 2) { + val nid = cards.first().card.nid + suspend(col.getNote(nid)) + ensureOpsExecuted(1) { + selectAll() + toggleSuspendCards() + assertAllSuspended("mixed selection -> suspend all") + } + } + + @Test + fun `suspend - notes - some cards suspended`() = runViewModelNotesTest(notes = 2) { + // this suspends o single cid from a nid + suspend(cards.first()) + ensureOpsExecuted(1) { + selectAll() + toggleSuspendCards() + assertAllSuspended("mixed selection -> suspend all") + } + } + + fun `suspend cards - notes - none suspended`() = runViewModelNotesTest(notes = 2) { + ensureOpsExecuted(1) { + selectAll() + toggleSuspendCards() + assertAllSuspended("none suspended -> suspend all") + } + } + + private fun runViewModelNotesTest( + notes: Int = 0, + manualInit: Boolean = true, + testBody: suspend CardBrowserViewModel.() -> Unit + ) = + runTest { + with(col) { CardsOrNotes.NOTES.saveToCollection() } + for (i in 0 until notes) { + // ensure 1 note = 2 cards + addNoteUsingBasicAndReversedModel() + } + val viewModel = CardBrowserViewModel( + lastDeckIdRepository = SharedPreferencesLastDeckIdRepository(), + cacheDir = createTransientDirectory(), + options = null, + preferences = AnkiDroidApp.sharedPreferencesProvider, + manualInit = manualInit + ) + // makes ignoreValuesFromViewModelLaunch work under test + if (manualInit) { + viewModel.manualInit() + } + testBody(viewModel) + } + + private fun runViewModelTest( + notes: Int = 0, + manualInit: Boolean = true, + testBody: suspend CardBrowserViewModel.() -> Unit + ) = runTest { for (i in 0 until notes) { addNoteUsingBasicModel() } @@ -442,3 +575,44 @@ internal suspend fun CardBrowserViewModel.invokeInitialSearch() { // numberOfCardsToRenderFlow.emit(1) Timber.v("initial search completed") } + +private fun TestClass.assertAllSuspended(context: String) { + val cards = col.findCards("").map { col.getCard(it) } + assertThat("performance", cards.size, lessThan(10)) + + for (card in cards) { + assertThat( + "$context: all cards are unsuspended", + card.queue, + equalTo(QUEUE_TYPE_SUSPENDED) + ) + } +} + +private fun TestClass.assertAllUnsuspended(context: String) { + val cards = col.findCards("").map { col.getCard(it) } + assertThat("performance", cards.size, lessThan(10)) + + for (card in cards) { + assertThat( + "$context: all cards unsuspended", + card.queue, + not(equalTo(QUEUE_TYPE_SUSPENDED)) + ) + } +} + +private fun TestClass.suspendAll() { + col.findCards("").also { cards -> + col.sched.suspendCards(col.findCards("")) + Timber.d("suspended %d cards", cards.size) + } +} + +private fun TestClass.suspend(vararg cards: CardBrowser.CardCache) { + col.sched.suspendCards(cards.map { it.id }) +} + +private fun TestClass.suspend(note: Note) { + col.sched.suspendCards(note.cardIds(col)) +} diff --git a/AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt b/AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt new file mode 100644 index 000000000000..c48d2309d075 --- /dev/null +++ b/AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024 David Allison + * + * 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 . + */ + +package com.ichi2.testutils + +import com.ichi2.libanki.ChangeManager +import com.ichi2.libanki.undoableOp +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import timber.log.Timber + +/** + * Ensures no calls to [ChangeManager.notifySubscribers] via [undoableOp] + */ +suspend fun ensureNoOpsExecuted(block: suspend () -> Unit) { + var changes = false + ChangeManager.subscribe { _, _ -> + Timber.d("ChangeManager op detected") + changes = true + } + block() + // we should be fine to not cleanup here + assertThat("ChangeManager should not be called", !changes) +} + +/** + * Ensures no calls to [ChangeManager.notifySubscribers] via [undoableOp] + */ +suspend fun ensureOpsExecuted(count: Int, block: suspend () -> Unit) { + var changes = 0 + ChangeManager.subscribe { _, _ -> + Timber.d("ChangeManager op detected") + changes++ + } + block() + // we should be fine to not cleanup here, as the subscriber goes out of scope + assertThat("ChangeManager: expected $count calls", changes, equalTo(count)) +} From 4396544bfb77ecd48e99d288cb7e7b59f5f3dda8 Mon Sep 17 00:00:00 2001 From: Shruti Gitte Date: Mon, 3 Jun 2024 13:05:59 +0530 Subject: [PATCH 034/138] refactor: extract text/plain as constant (#16518) * refactor: extract text/plain as constant * remove extra constant * refactor:constant location --- .../androidTest/java/com/ichi2/anki/NoteEditorIntentTest.kt | 3 ++- .../com/ichi2/anki/dialogs/ImportFileSelectionFragment.kt | 3 ++- AnkiDroid/src/main/java/com/ichi2/utils/AssetHelper.kt | 5 ++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/NoteEditorIntentTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/NoteEditorIntentTest.kt index 7ea7a72fff7d..5ec743711713 100644 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/NoteEditorIntentTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/NoteEditorIntentTest.kt @@ -26,6 +26,7 @@ import com.ichi2.anki.tests.InstrumentedTest import com.ichi2.anki.testutil.GrantStoragePermission import com.ichi2.testutils.Flaky import com.ichi2.testutils.OS +import com.ichi2.utils.AssetHelper.TEXT_PLAIN import junit.framework.TestCase.assertFalse import org.hamcrest.MatcherAssert import org.hamcrest.Matchers @@ -62,7 +63,7 @@ class NoteEditorIntentTest : InstrumentedTest() { fun intentLaunchedWithNonImageIntent() { val intent = Intent().apply { action = Intent.ACTION_SEND - type = "text/plain" + type = TEXT_PLAIN } assertFalse(intentLaunchedWithImage(intent)) } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportFileSelectionFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportFileSelectionFragment.kt index ededf4186b88..9bf85fd99423 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportFileSelectionFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportFileSelectionFragment.kt @@ -30,6 +30,7 @@ import com.ichi2.anki.AnkiActivity import com.ichi2.anki.R import com.ichi2.anki.analytics.UsageAnalytics import com.ichi2.annotations.NeedsTest +import com.ichi2.utils.AssetHelper.TEXT_PLAIN import com.ichi2.utils.title import kotlinx.parcelize.Parcelize import timber.log.Timber @@ -96,7 +97,7 @@ class ImportFileSelectionFragment : DialogFragment() { multiple = false, mimeType = "*/*", extraMimes = arrayOf( - "text/plain", + TEXT_PLAIN, "text/comma-separated-values", "text/csv", "text/tab-separated-values" diff --git a/AnkiDroid/src/main/java/com/ichi2/utils/AssetHelper.kt b/AnkiDroid/src/main/java/com/ichi2/utils/AssetHelper.kt index 99ae62d9d476..34c6c46f1459 100644 --- a/AnkiDroid/src/main/java/com/ichi2/utils/AssetHelper.kt +++ b/AnkiDroid/src/main/java/com/ichi2/utils/AssetHelper.kt @@ -68,7 +68,10 @@ object AssetHelper { "js" -> "text/javascript" "mjs" -> "text/javascript" "json" -> "application/json" - else -> MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) ?: "text/plain" + else -> MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) ?: TEXT_PLAIN } } + + /** Used for mime type or Intent type when sharing text via other applications **/ + const val TEXT_PLAIN = "text/plain" } From 74feec0a3dd157d9c3a332f6a3819d2a9154effc Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Sun, 2 Jun 2024 17:54:03 -0500 Subject: [PATCH 035/138] fix(i18n): file 15-markettitle.txt is gone, remove remnants Related to PR 16348 - the file is no longer needed as it was for the special (now defunct) ChromeOS store. We stopped processing it, but we were still uploading it for translation (and the file was still up in crowdin so being downloaded...) --- tools/localization/src/constants.ts | 1 - tools/localization/src/update.ts | 1 - tools/localization/src/upload.ts | 7 ------- 3 files changed, 9 deletions(-) diff --git a/tools/localization/src/constants.ts b/tools/localization/src/constants.ts index dfeeb56740d1..0f5d73654f95 100644 --- a/tools/localization/src/constants.ts +++ b/tools/localization/src/constants.ts @@ -62,7 +62,6 @@ export const I18N_FILES = [ "11-arrays", "12-dont-translate", "14-marketdescription", - "15-markettitle", "16-multimedia-editor", "17-model-manager", "18-standard-models", diff --git a/tools/localization/src/update.ts b/tools/localization/src/update.ts index cd1b42687f21..d347fcbda83d 100644 --- a/tools/localization/src/update.ts +++ b/tools/localization/src/update.ts @@ -81,7 +81,6 @@ async function replacechars(fileName: string): Promise { */ function fileExtFor(f: string): string { if (f == "14-marketdescription") return ".txt"; - else if (f == "15-markettitle") return ".txt"; else return ".xml"; } diff --git a/tools/localization/src/upload.ts b/tools/localization/src/upload.ts index 5026f6bce7d7..75f9f2575e85 100644 --- a/tools/localization/src/upload.ts +++ b/tools/localization/src/upload.ts @@ -38,13 +38,6 @@ export async function uploadI18nFiles() { let I18N_FILE_TARGET_NAME = `${file}.xml`; let I18N_FILE_SOURCE_NAME = `${I18N_FILES_DIR}${I18N_FILE_TARGET_NAME}`; - // special case, the title is just the name as one line, it is ephemeral so create it - if (file == "15-markettitle") { - I18N_FILE_TARGET_NAME = "15-markettitle.txt"; - I18N_FILE_SOURCE_NAME = path.join(TEMP_DIR, "15-markettitle.txt"); - fs.writeFileSync(I18N_FILE_SOURCE_NAME, TITLE_STR); - } - // special case, the market description is a txt file from different location if (file == "14-marketdescription") { I18N_FILE_TARGET_NAME = "14-marketdescription.txt"; From 09b17d3ffc9c34867a3a1a21f01b67a2d02911bf Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Sun, 2 Jun 2024 20:15:53 +0100 Subject: [PATCH 036/138] fix: ` Ang mga kard ay tinanggal na%d Nabigong makakuha ng permiso na gamitin ang mikropono. - Could not obtain camera permission. Functionality has been disabled. - Failed to open Multimedia Editor + Hindi makamit ang permiso sa kamera. Hindi pinagana ang katanginang ito. + Bigong buksan ang Multimedia Editor - Audio recording permission denied - Unknown error occurred displaying Advanced Editor + Hindi binigyang permiso na mag-record ng audio + Hindi malamang kamalian ang nangyari habang pinapakita ang Advanced Editor Na-upgrade ang AnkiDroid Na-upgrade na ang AnkiDroid. Ang upgrade na ito ay naglalaman ng pag-aayos sa mga posibleng problema sa database, at pinapayuhan ka namin na suriin ang database ngayon. @@ -157,8 +157,8 @@ Mga file na may di-wastong pag-encode:%d Hindi Angkop Ang Bersyon ng Database Mas abante ang database na ito kumpara sa bersyong kayang gamitin ng AnkiDroid. I-upgrade o i-downgrade ang database ng AnkiDroid upang mabuksan ito\n\nBersyon na suportado: %1$d\nBersyon ng database: %2$d\n\nAng sumusunod na mga opsyon sa pagbalik ay posibleng sapawan ang kasalukuyan mong koleksyon ng isang angkop na bersyon ng database. - Na-apply ang larawan sa background - Background image removed + Inapply ang larawan sa background + Tinanggal ang larawan sa background Walang napiling larawan May mali sa pagpili ng larawan. Mangyari na tingnan ang gabay. %s May mali sa pagbura ng larawan diff --git a/AnkiDroid/src/main/res/values-fil/05-feedback.xml b/AnkiDroid/src/main/res/values-fil/05-feedback.xml index d7658592b21f..74b59192208e 100644 --- a/AnkiDroid/src/main/res/values-fil/05-feedback.xml +++ b/AnkiDroid/src/main/res/values-fil/05-feedback.xml @@ -48,12 +48,12 @@ Mode ng pag-uulat ng error Disclaimer: Hindi kami nangongolekta ng anumang personal na impormasyon tulad ng iyong email address, numero ng telepono, o IMEI ng iyong telepono. Kinokolekta namin ang ilang impormasyon tungkol sa iyong device tulad ng manufacturer, modelo at bersyon ng Android, pati na rin ang likas na katangian ng iniulat na mga error sa kanilang sarili at ang mga hakbang na humantong sa kanila na nagaganap. - AnkiDroid Feedback + Feedback sa AnkiDroid Ipasok ang iyong komentaryo o impormasyon tungkol sa likas na katangian ng anumang mga error na iyong naiulat. Nakaranas ang AnkiDroid ng problema; isang ulat ay ipinadala sa mga developer… - An error report is being prepared for the developers… + Naghahanda ng ulat sa kamalian para sa mga developer… Kopyahin ang impormasyon ng pag-debug Report Magpadala ng mga ulat ng error nang awtomatiko - No suitable app found + Walang mahanap na angkop na app diff --git a/AnkiDroid/src/main/res/values-fil/07-cardbrowser.xml b/AnkiDroid/src/main/res/values-fil/07-cardbrowser.xml index 77fc91ba43f2..a88a76dfee26 100644 --- a/AnkiDroid/src/main/res/values-fil/07-cardbrowser.xml +++ b/AnkiDroid/src/main/res/values-fil/07-cardbrowser.xml @@ -46,28 +46,28 @@ - %d card ipinapakita - %d na mga card ipinapakita + %d card ang pinapakita + %d card ang pinapakita - %d note shown - %d notes shown + %d tala ang pinapakita + %d tala ang pinapakita Lahat ng decks - Delete card - Delete cards + Burahin ang card + Burahin ang mga card - Delete note - Delete notes + Burahin ang tala + Burahin ang mga tala - Change deck + Palitan ang deck Burahin ang tala? I-filter ang mga minarkahan I-filter ang mga suspendido I-filter ayon sa tag - Filter by flag + Isala ayon sa watawat Aking mga paghahanap I-save ang paghahanap Mamili na nai-save na na paghahanap @@ -82,34 +82,34 @@ No sorting (mas mabilis) Sa pamamagitan ng uri ng field Sa pamamagitan ng oras - By note modification time - By card modification time + Sa oras na binago ang tala + Sa oras na binago ang card Sa pamamagitan ng oras na nakatakda Sa pamamagitan ng agwat Sa pamamagitan ng kagaanan Sa pamamagitan ng pagrepaso Sa pamamagitan ng pagdaan ng panahon - Select all - Select none - (new) - (filtered) - (learning) - No cards found in deck ‘%s’ - Search all decks - Unknown - Truncate content - Today is ‘0 %1$s’, tomorrow is ‘1 %2$s’, etc… + Piliin lahat + Walang piliin + (bago) + (nasala) + (pinag-aaralan) + Walang mga card na nahanap sa deck na\'%s\' + Hanapin sa lahat ng deck + Hindi Matukoy + Na-truncate na content + Ngayon ay \'0 %1$s\', bukas ay \'1 %2$s\', atbp… - Export card - Export cards + I-export ang card + I-export ang mga card - Export note - Export notes + I-export ang tala + I-export ang mga tala - %d card deleted - %d cards deleted + %d card ang natanggal + %d card ang natanggal diff --git a/AnkiDroid/src/main/res/values-fil/08-widget.xml b/AnkiDroid/src/main/res/values-fil/08-widget.xml index 8c2ebf4b97d5..ce87f5197acb 100644 --- a/AnkiDroid/src/main/res/values-fil/08-widget.xml +++ b/AnkiDroid/src/main/res/values-fil/08-widget.xml @@ -47,8 +47,8 @@ Nakatakdang mga card - %d AnkiDroid card due - %d AnkiDroid cards due + %d nakatakdang AnkiDroid card + %d nakatakdang mga AnkiDroid card Maliit na AnkiDroid diff --git a/AnkiDroid/src/main/res/values-fil/09-backup.xml b/AnkiDroid/src/main/res/values-fil/09-backup.xml index 693a3aa0bffc..dddc96749fb7 100644 --- a/AnkiDroid/src/main/res/values-fil/09-backup.xml +++ b/AnkiDroid/src/main/res/values-fil/09-backup.xml @@ -44,13 +44,13 @@ ~ this program. If not, see . --> - Backup not saved. Not enough space left on your storage. Lower the backup depth or remove some other files. - Less than %d MB space on your storage left.\nFree some space to avoid data loss. + Hindi nai-save ang backup. Hindi sapat ang bakanteng space sa iyong storage. Ibaba ang backup na depth o magtanggal ng ibang mga file. + Mas mababa sa %d MB ang natirang space sa iyong storage. \nMaglagay ng space upang maiwasan ang pagkawala ng datos. Ibalik mula sa backup Bagong koleksyon Burahin ang koleksyon at gumawa ng bago Tanggalin ang koleksyon at lumikha ng bago? Buburahin nito ang lahat ng iyong progreso sa pag-aaral at tanggalin ang lahat ng baraha. - One-way sync from server + Isang-daanang sync mula sa server I-overwrite ang iyong koleksyon sa isa mula sa AnkiWeb? Ibababa nito ang lahat ng iyong progreso sa pag-aaral at idinagdag ang impormasyon mula noong huling pag-sync mo. Error handling Mga opsyon diff --git a/AnkiDroid/src/main/res/values-fil/10-preferences.xml b/AnkiDroid/src/main/res/values-fil/10-preferences.xml index 608120faa2df..6a7f14c2f8d0 100644 --- a/AnkiDroid/src/main/res/values-fil/10-preferences.xml +++ b/AnkiDroid/src/main/res/values-fil/10-preferences.xml @@ -158,32 +158,32 @@ Mas mabilis ang hardware render pero maaring magkaroon ng mga problema, lalo na sa Android 8/8.1. Kung hindi mo makita ang ibang bahagi ng user interface sa pag-repaso ng card, subukan ang setting na ito. Ligtas na display mode Hindi paganahin ang lahat ng animasyon at gumamit ng mas ligtas na paraan ng paghatak ng card. Maaaring kailanganin ito ng mga e-ink na device. - Disable Single-Field Edit Mode + I-disable Ang Single-Field Edit Mode - Allows \'Cloze Deletion\' context menu when in landscape mode. + Papayagan ang context menu na \'Pagbura ng Cloze\' tuwing gagamit ng landscape mode. Center align Patayo ang nilalaman ng mga baraha - Double tap time interval (milliseconds) - A second tap of the answer buttons will be ignored if this time has not elapsed. This prevents accidental double taps - Show answer long-press time - Minimum pressing time before the show answer button registers a touch. + Pagitan ng dalawang pindot (milliseconds) + Ang ikalawang pindot sa pindutanan ng answer ay babalewalain kung hindi lilipas ang oras na tinakda dito. Iniiwasan nito ang hindi sinasadyang dalawang pindot. + Oras ng mahabang-pindot sa \'Ipakita ang Sagot\' + Pinakamaikling oras sa pagpindot bago irehistro ang pagpindot sa \'Ipakita ang Sagot\' Ipakita ang oras ng button Ipakita ang susunod na oras ng pagsusuri sa mga pindutan ng sagot - Show large answer buttons - Show answer button in 2 rows - Show top bar - Show card counts, flag and mark in top bar + Gumamit ng Malaking Pindutan Pangsagot + Gumamit ng dalawang hanay sa mga pindutan pangsagot. + Ipakita ang ibabaw na bar + Ipakita ang bilang ng card, watawat, at marka sa ibabaw na bar Ipakita ang natitira Ipakita ang natitirang bilang ng card - Show ETA - Show remaining time + Ipakita ang ETA + Ipakita ang natitirang oras Deck para sa mga bagong card Matuto nang higit na limitasyon Limitasyon ng oras ng Timebox - Start of next day + Simula ng susunod na araw - %d hour past midnight - %d hours past midnight + %d oras makalipas ang hating-gabi + %d oras makalipas ang hating-gabi Panatilihin ang screen Huwag paganahin ang timeout ng screen @@ -195,40 +195,40 @@ Ipakita kung room Menu lamang I-reset sa default - Reset settings to default + Ibalik ang mga setting sa default Reset - Third-party API apps - See a list of applications which make use of the AnkiDroid API such as dictionaries, utilities. + Third-party na mga API app + Ipakit ang listahan ng aplikasyon na gumagamit sa API ng AnkiDroid tulad ng mga diksyunaryo, utility. Reviewer - Show deck title - Accessibility + Ipakita ang pamagat ng deck + Aksesibilidad - Paste clipboard images as PNG - By default Anki pastes images on the clipboard as JPG files to save disk space. You can use this option to paste as PNG images instead. - Press back twice to go back/exit - To avoid accidentally leaving the reviewer or the app + I-paste ang larawan sa clipboard na PNG + PIne-paste ng ng Anki ang mga larawan sa clipboard bilang JPG na file ng default upang magtipid sa disk spacee. Maaari mong gamiting ang opsyon na ito upang i-paste ang mga larawan bilang PNG. + Pindutin ang balik kalawa para bumalik/umalis + Upang maiwasan ang hindi sinasadyang pag-alis sa reviewer o sa mismong app - Allow all files in media imports - If Android doesn’t recognize a media file + Payagan lahat ng file sa pag-angkat ng media + Kung hindi nakikilala ng Android ang isang media file Pasadyang pag-sync ng server - Not used - Learn more + Hindi ginagamit + Alamin pa ]]> Sync url Keyboard Bluetooth - Answer buttons + Pindutan Pangsagot Card - Note - Navigation + Tala + Nabigasyon Media - Misc + Iba pa Piliin ang mga tag @@ -240,36 +240,36 @@ napili ng mga kard Reschedule Reschedule cards batay sa aking mga sagot sa deck na ito - Enable second filter + Paganahin ang pangalawang pansala Tukuyin ang mga pasadyang hakbang - Preview delays - Delays are in seconds. 0 returns card to original deck. + Antala sa pag-preview + Ang antala ay naka-segundo. 0 kung ibabalik ang card sa orihinal nito na deck. - Help make AnkiDroid better! - Share feature usage - You can contribute to AnkiDroid by helping the development team see which features people use - Replace newlines with HTML - In the Note Editor, convert any instances of <br> to newlines when editing a card. - Focus ‘type in answer’ - Automatically focus the ‘type in answer’ field in the reviewer + Tulungang pabutihin pa ang AnkiDroid! + Ibahagi ang paggamit ng mga katangian + Maaari ka mag-ambag sa AnkiDroid sa pagtulong sa development team na makita ang mga katangiang madalas ginagamit ng mga tao + Palitan ang mga newlines ng HTML + Sa Note Editor, palitan ang mga instansya ng <br> ng newlines tuwing nag-eedit ng card. + Tampulan ang \'i-type ang sagot\' + Kusa na tatampulan ang \'i-type ang sagot\' na field sa reviewer - Open Changelog - About - Contributors - contributors. You can help AnkiDroid too by programming, translating, donating and more!]]> - License - GPL-3.0 and AGPL-3.0 licenses, with the source code available on GitHub]]> - donating. Any amount is deeply appreciated.]]> + Buksan Ang Changelog + Tungkol sa Amin + Mga Nag-Ambag + nag-ambag. Maaari ka ring tumulong sa AnkiDroid sa pag-program, pagsalin, paghandog at iba pa!]]> + Lisensya + GPL-3.0 at AGPL-3.0 na mga lisensya, kung saan ang mga source code nito ay mahahanap sa GitHub]]> + paghahandog. Lubos naming ipinapasalamat ang anumang halaga.]]> - Add gesture - Replace gesture - Add key - Replace key - Press a key - Add joystick/motion controller - Move a joystick/motion controller - User actions - Trigger JavaScript from the review screen + Magdagdag ng gesture + Palitan ang gesture + Magdagdag ng key + Palitan ang key + Pindutin ang key + Magdagdag ng joystick/motion controller + Igalaw ang joystick/motion controller + Mga aksyon ng user + Paganahin ang JavaScript sa review screen Aksyon ng user 1 Aksyon ng user 2 Aksyon ng user 3 @@ -280,7 +280,7 @@ Aksyon ng user 8 Aksyon ng user 9 - Select card side + Pumili ng panig ng card Tanong Sagot Tanong & Sagot @@ -289,11 +289,11 @@ %s Tanggalin ang \'%s\' - Already bound to ‘%s’ + Nakakabit na sa \'%s\' Eksperimental - AnkiDroid has introduced a better TTS mechanism which is compatible with other Anki clients and includes more voices and improvements to language playback!\n\nPlease upgrade as soon as possible, as this setting will be removed soon - Please upgrade to the new text to speech format + Sinimulan ng AnkiDroid ang mas pinagaling na mekanismo sa TTS kung saan ito ay gagana sa iba\'t ibang kliyente ng Anki at mayroon itong mas maraming boses at mas pinagaling na playback ng wika! Mangyaring mag-upgrade sa lalong madaling panahon, dahil mawawal na ang setting na ito. + Mangyaring mag-upgrade sa bagong text to speech na format Mga opsyon pangdeveloper Paganahin ang mga opsyon pangdeveloper @@ -332,32 +332,32 @@ Burahin ang mga imahe at ibang media na hindi nagsisimula sa _ at hindi ginagamit ng kahit anong mga tala. Burahin ang walang gamit na media file - Delete backups - Delete backups - Deleting backups… + Burahin ang mga backup + Burahin ang mga backup + Binubura ang mga backup… - Delete collection - Delete collection, media, and backups. App settings are not deleted - Delete collection - Are you sure you want to delete your collection, media, and backups?\n\nNote: this action will close the window. - Deleting collection… + Burahin ang koleksyon + Buburahin nito ang kolekyon, media, at mga backup. Hindi nito buburahin ang mga setting ng app + Burahin ang koleksyon + Sigurado ka ba na burahin ang iyong koleksyon, media, at mga backup?\n\nTandaan: isasara ng aksyong ito ang window. + Binubura ang koleksyon… - Delete everything - Delete collection, media, backups, and settings - Delete everything - Are you sure you want to delete all data? This includes your collection, media, backups and preferences.\n\nNote: this action will close the window. + Burahin lahat + Burahin ang mga koleksyon, media, backup, at setting + Burahin lahat + Sigurado ka ba na burahin ang lahat ng iyong mga datos? Kasami dito ang iyong mga koleksyon, media, backup, at setting.\n\nTandaan: Isasara ng aksyong ito ang window. - Delete app data - Delete settings and other app data - Delete app data - Are you sure you want to delete app data? This includes settings and other app data.\n\nNote: this action will close the window. + Burahin ang datos ng app + Burahin ang mga setting at iba pang datos sa app + Burahin ang datos ng app + Sigurado ka ba na burahin ang mga datos ng app? Kasama dito ang mga setting at iba pang datos ng app.\n\nTandaan: Isasara ng aksyong ito ang window. - No collection - Error - Fetching… - Calculating… - Collection does not exist + Walang koleksyon + Kamalian + Kinukuha… + Kinakalkula… + Hindi umiiral ang koleksyon diff --git a/AnkiDroid/src/main/res/values-fil/11-arrays.xml b/AnkiDroid/src/main/res/values-fil/11-arrays.xml index 1c81c64d20d0..d70cb448b7a8 100644 --- a/AnkiDroid/src/main/res/values-fil/11-arrays.xml +++ b/AnkiDroid/src/main/res/values-fil/11-arrays.xml @@ -56,14 +56,14 @@ Pagpapababa ng mga agwat Karamihan ay natapos na Idinagdag ang order - Order due + Nakatakdang order Pinakabagong inaidagdag muna - Relative overdueness + Kaukulang kadukado Gumamit ng kasalukuyang deck Magpasya ayon sa uri ng tala - Follow system + Sundin ang system Banayad Plain @@ -71,35 +71,35 @@ Itim Madilim - xx-small - x-small - small - medium - large - x-large - xx-large + pinakamaliit + sobrang liit + maliit + katamtaman + malaki + sobrang laki + pinakamalaki - Answer again - Answer hard - Answer good - Answer easy + Sagot - muli + Sagot - mahirap + Sagot - mabuti + Sagot - madali I-play ang media Abort sa pag-aaral - Toggle Red Flag - Toggle Orange Flag - Toggle Green Flag - Toggle Blue Flag - Toggle Pink Flag - Toggle Turquoise Flag - Toggle Purple Flag - Remove Flag - Page Up - Page Down - Abort Learning and Sync - Toggle Whiteboard - Show Hint - Show All Hints - Record Voice - Replay Voice - Save Recording + Maglagay ng Pulang Watawat + Maglagay ng Kahel na Watawat + Maglagay ng Berdeng Watawat + Maglagay ng Asul na Watawat + Maglagay ng Rosas na Watawat + Maglagay ng Turkesa na Watawat + Maglagay ng Ube na Watawat + Tanggalin ang Watawat + Itaas ang Pahina + Ibaba ang Pahina + Iudlot Ang Pag-Aaral at Pag-Sync + Paganahin ang Puting Pisara + Ipakita Ang Hint + Ipakita Ang Lahat ng Hint + I-rekord Ang Boses + I-play Muli Ang Boses + I-save Ang Recording diff --git a/AnkiDroid/src/main/res/values-fil/16-multimedia-editor.xml b/AnkiDroid/src/main/res/values-fil/16-multimedia-editor.xml index 03d2ece8d8c0..adab70279732 100644 --- a/AnkiDroid/src/main/res/values-fil/16-multimedia-editor.xml +++ b/AnkiDroid/src/main/res/values-fil/16-multimedia-editor.xml @@ -41,8 +41,8 @@ Magdagdag ng larawan - Add audio clip - Add video clip + Magdagdag ng audio clip + Magdagdag ng video clip Mag-record ng audio Advanced na editor Alisin ang pagtanggal @@ -50,7 +50,7 @@ Text Imahe - Audio recording + Recording ng Audio Audio Clip Tapos @@ -71,22 +71,22 @@ May nagkamali - SVGs are not available for preview - Error converting clipboard image to png: %s + Hindi magamit ang mga SVG sa pag-preview + May mali sa pag-convert ng larawan sa clipboard at gawing png: %s Maglagay ng nilalaman ng multimedia sa field ng%1$s Maglakip ng media Nabigo ang pag-record Nabigo ang pag-play - Unable to create recorder tool bar + Hindi makagawa ng tool bar ng recorder Nabigo ang pag-edit - Do you want to crop this image? - Crop image - Current image size is %sMB. Default image size limit is 1MB. Do you want to crop it? - "Select image failed, Please retry" - App returned an unexpected value. You may need to use a different app - Field Contents + Gusto mo bang i-crop ang larawan + I-crop ang larawan + Ang laki ng kasalukuyang larawan ay %sMB. Ang default na hangganan ng laki ng larawan ay 1MB. Gusto mo pa rin ba itong i-crop? + "Bigo na mapili ang larawan. Mangyaring ulitin" + Nagbalik ng hindi inaasahang halaga ang app. Maaaring kailangan mo gumamit ng ibang app + Mga Laman ng Field diff --git a/AnkiDroid/src/main/res/values-fil/17-model-manager.xml b/AnkiDroid/src/main/res/values-fil/17-model-manager.xml index f76dddfdb821..ca30c093e542 100644 --- a/AnkiDroid/src/main/res/values-fil/17-model-manager.xml +++ b/AnkiDroid/src/main/res/values-fil/17-model-manager.xml @@ -50,36 +50,36 @@ Palitan ang pangalan ng uri ng tala. - Set language hint to %s + I-set ang hint sa wika sa %s I-edit ang mga patlang Magdagdag ng field Tanggalin ang patlang Palitan ang pangalan ng patlang - Set keyboard language hint + I-set ang hint ng wika ng keyboard Reposition field Reposition field (magpasok ng halaga%1$d-%2$d) - Remember last input when adding + Tandaan ang huling input tuwing nagdaragdag Ina-update ang mga patlang Ayusin ayon sa patlang na ito - Are you sure you wish to delete this note type? + Sigurado ka ba na nais mong burahin ang uri ng tala na ito? Sigurado ka bang nais mong tanggalin ang field na ito? Magdagdag ng:%1$s I-clone:%1$s - Enter the template that the card browser will use to display your cards. Use this to display a more concise answer.\n\nA front template of\n“The capital of {{Country}} is:”\ncould be compressed in the card browser to\n“Capital: {{Country}}” - Question Format - Answer Format - Restore Default Values? - These changes are applied when the card template is saved + Ilagay ang template na gagamitin ng card browser upang maipakita ang iyong mga card. Gamitin ito upang maipakita ang mas maiksi na sagot.\n\nAng harap na template ng\n\"Ang kabisera ng {{Country}} ay:\"\nay maaaring paiksiin sa card browser bilang\n\"Kabisera: {{Country}}\" + Format ng Tanong + Format ng Sagot + Ibalik sa Default na Halaga? + Ang pagbabagong ito ay ma-aapply tuwing isesave ang card template - Deck override (on) - Deck override (off) - Set ‘%1$s’ default deck to ‘%2$s’ - Removed default deck for ‘%s’ - Select deck to place new ‘%s’ cards into - Filter decks + I-override ang deck (bukas) + I-override ang deck (sara) + I-set ang default deck na \'%1$s\' ng \'%2$s\' + Tinanggal ang default deck para sa \'%s\' + Pumili ng deck na paglalagyan ng mga bagong card ng \'%s\' + Salain ang mga deck diff --git a/AnkiDroid/src/main/res/values-fil/18-standard-models.xml b/AnkiDroid/src/main/res/values-fil/18-standard-models.xml index df9981b51426..3940df947940 100644 --- a/AnkiDroid/src/main/res/values-fil/18-standard-models.xml +++ b/AnkiDroid/src/main/res/values-fil/18-standard-models.xml @@ -26,15 +26,15 @@ - Front - Back - Text - Back Extra - Add Reverse + Harapan + Likuran + Teksto + Ekstra sa Likuran + Magdagdag ng Kabalikan Basic Cloze - Basic (type in the answer) - Basic (and reversed card) - Basic (optional reversed card) + Basic (i-type ang sagot) + Basic (at may kabalikan na card) + Basic (opsyonal na kabalikan na card) diff --git a/AnkiDroid/src/main/res/values-fil/20-search-preference.xml b/AnkiDroid/src/main/res/values-fil/20-search-preference.xml index 209a8cfe4f8a..eed8eba1af44 100644 --- a/AnkiDroid/src/main/res/values-fil/20-search-preference.xml +++ b/AnkiDroid/src/main/res/values-fil/20-search-preference.xml @@ -60,6 +60,6 @@ the key names MUST NOT be changed due to this --> - Search… - Clear history + Maghanap… + Burahin ang historya diff --git a/AnkiDroid/src/main/res/values-gu/01-core.xml b/AnkiDroid/src/main/res/values-gu/01-core.xml index 9193aeda8d18..c9470d9c2500 100644 --- a/AnkiDroid/src/main/res/values-gu/01-core.xml +++ b/AnkiDroid/src/main/res/values-gu/01-core.xml @@ -133,20 +133,20 @@ અભિનંદન! તમે હમણાં માટે સમાપ્ત કર્યું છે. હજુ સુધી કોઈ કાર્ડ બાકી નથી ઉપકરણ સંગ્રહ માઉન્ટ થયેલ નથી - Sync + સમન્વયન સ્કોપ્ડ સ્ટોરેજ પર સ્થાનાંતરિત કરો શું તમે સમન્વયન રદ કરવા માંગો છો? સિંક કરવાનું ચાલુ રાખો - Sync cancelled - Cancelling…\nThis may take some time. - Syncing media + સમન્વયન રદ કર્યું + રદ કરી રહ્યું છે…\nઆમાં થોડો સમય લાગી શકે છે. + મીડિયા સમન્વયિત કરી રહ્યું છે નિકાસ ડેક કંઈ નહીં કાર્ડ પ્રકારો ફ્રન્ટ ટેમ્પલેટ પાછળનો નમૂનો - Styling + સ્ટાઇલીંગ કાર્ડ બ્રાઉઝર દેખાવ ડેક ઓવરરાઇડ ફીલ્ડ દાખલ કરો @@ -157,93 +157,93 @@ આ %1$d કાર્ડ બનાવશે. આગળ વધીએ? - Delete the “%2$s” card type, and its %1$d card? - Delete the “%2$s” card type, and its %1$d cards? + “%2$s” કાર્ડનો પ્રકાર અને તેનું %1$d કાર્ડ કાઢી નાખીએ? + \"%2$s\" કાર્ડનો પ્રકાર અને તેના %1$d કાર્ડ કાઢી નાખીએ? - Removing this card type would cause one or more notes to be deleted. Please create and save a new card type first. - Unable to save card template changes: %s - The card type for the current card was deleted. + આ કાર્ડ પ્રકારને દૂર કરવાથી એક અથવા વધુ નોંધો કાઢી નાખવામાં આવશે. કૃપા કરીને પહેલા એક નવો કાર્ડ પ્રકાર બનાવો અને સાચવો. + કાર્ડ ટેમ્પલેટ ફેરફારો સાચવવામાં અસમર્થ: %s + વર્તમાન કાર્ડ માટે કાર્ડનો પ્રકાર કાઢી નાખવામાં આવ્યો હતો. - Browser appearance + બ્રાઉઝર દેખાવ કાર્ડ માહિતી - Read and write to the AnkiDroid database - access existing notes, cards, note types, and decks, as well as create new ones + AnkiDroid ડેટાબેઝ વાંચો અને લખો + હાલની નોંધો, કાર્ડ્સ, નોંધના પ્રકારો અને ડેકને ઍક્સેસ કરો તેમજ નવી બનાવો - Card Browser - Anki Card + કાર્ડ બ્રાઉઝર + અંકી કાર્ડ - The collections can’t be combined.\nWhich collection do you want to keep? + સંગ્રહોને જોડી શકાતા નથી.\nતમે કયો સંગ્રહ રાખવા માંગો છો? AnkiDroid - AnkiWeb - Replace your collection on AnkiDroid with your collection from AnkiWeb? - Replace your collection on AnkiWeb with your collection from AnkiDroid? - Select collection to keep - Replace collection + અંકીવેબ + AnkiDroid પરના તમારા સંગ્રહને AnkiWeb ના તમારા સંગ્રહ સાથે બદલીએ? + AnkiWeb પરના તમારા સંગ્રહને AnkiDroid ના તમારા સંગ્રહ સાથે બદલીએ? + રાખવા માટે સંગ્રહ પસંદ કરો + સંગ્રહ બદલો - %1$d card (0 due) - %1$d cards (0 due) + %1$d કાર્ડ (0 બાકી) + %1$d કાર્ડ્સ (0 બાકી) - Cannot write to or create file %s - "Multiple errors, most recent: %s" - Multiple consecutive errors without progress, most recent: %s + ફાઇલ %s પર લખી અથવા બનાવી શકાતી નથી + "બહુવિધ ભૂલો, સૌથી તાજેતરની: %s" + પ્રગતિ વિના એકથી વધુ સળંગ ભૂલો, સૌથી તાજેતરની: %s - Migrating database files - Copying… - Migrating media - Calculating transfer size… - Moved %1$s of %2$s - Migration successful - Your data has been migrated successfully. - AnkiDroid is fully functional again, and you can sync. + ડેટાબેઝ ફાઇલોનું સ્થળાંતર + કૉપિ કરી રહ્યાં છીએ… + સ્થાનાંતરિત મીડિયા + ટ્રાન્સફરના કદની ગણતરી કરી રહ્યાં છીએ… + %2$s માંથી %1$s ખસેડ્યું + સ્થળાંતર સફળ + તમારો ડેટા સફળતાપૂર્વક સ્થાનાંતરિત કરવામાં આવ્યો છે. + AnkiDroid ફરીથી સંપૂર્ણપણે કાર્યરત છે, અને તમે સમન્વયિત કરી શકો છો. \n - \nNote that your collection is now located in a folder that is removed when uninstalling the app. - Please make sure that your data is safe by regularly syncing or exporting backups. + \nનોંધ કરો કે તમારો સંગ્રહ હવે એવા ફોલ્ડરમાં સ્થિત છે જે એપ્લિકેશનને અનઇન્સ્ટોલ કરતી વખતે દૂર કરવામાં આવે છે. + કૃપા કરીને ખાતરી કરો કે તમારો ડેટા નિયમિતપણે સમન્વયિત અથવા બેકઅપ નિકાસ કરીને સુરક્ષિત છે. - Migration failed - સ્થળાંતર નિષ્ફળ થયું +
- The changes were reverted. + ફેરફારો પાછા ફર્યા.

- Please try re-running the migration. - To resolve the problem, you may need to free up some disk space, - or reconnect the removable storage that holds your collection. + કૃપા કરીને સ્થળાંતર ફરીથી ચલાવવાનો પ્રયાસ કરો. + સમસ્યાને ઉકેલવા માટે, તમારે કેટલીક ડિસ્ક જગ્યા ખાલી કરવાની જરૂર પડી શકે છે, + અથવા દૂર કરી શકાય તેવા સ્ટોરેજને ફરીથી કનેક્ટ કરો કે જે તમારા સંગ્રહને ધરાવે છે.

- Learn more and get help + વધુ જાણો અને મદદ મેળવો ]]>
-
- The changes were not reverted. - While no data should’ve been lost, - the media files might be split between the old and the new folder. + ફેરફારો હતા નથી પાછો ફર્યો + જ્યારે કોઈ ડેટા ગુમ ન થવો જોઈએ, + મીડિયા ફાઇલો જૂના અને નવા ફોલ્ડર વચ્ચે વિભાજિત થઈ શકે છે.

- Please try re-running the migration. - To resolve the problem, you may need to free up some disk space, - or reconnect the removable storage that holds your collection. + કૃપા કરીને સ્થળાંતર ફરીથી ચલાવવાનો પ્રયાસ કરો. + સમસ્યાને ઉકેલવા માટે, તમારે કેટલીક ડિસ્ક જગ્યા ખાલી કરવાની જરૂર પડી શકે છે, + અથવા દૂર કરી શકાય તેવા સ્ટોરેજને ફરીથી કનેક્ટ કરો કે જે તમારા સંગ્રહને ધરાવે છે.

- Learn more and get help + વધુ જાણો અને મદદ મેળવો ]]>
-
- Learn more and get help + વધુ જાણો અને મદદ મેળવો ]]>
- Resume migration - Inaccessible collection - We are unable to access your collection after AnkiDroid is uninstalled due to a change in Play Store Policy\n\nYour data is safe and can be restored. It is located at\n%s\n\nSelect an option below to restore: + સ્થળાંતર ફરી શરૂ કરો + અપ્રાપ્ય સંગ્રહ + પ્લે સ્ટોર નીતિમાં ફેરફારને કારણે AnkiDroid અનઇન્સ્ટોલ થયા પછી અમે તમારા સંગ્રહને ઍક્સેસ કરવામાં અસમર્થ છીએ\n\nતમારો ડેટા સુરક્ષિત છે અને તેને પુનઃસ્થાપિત કરી શકાય છે. તે\n%s પર સ્થિત છે\n\nપુનઃસ્થાપિત કરવા માટે નીચેનો વિકલ્પ પસંદ કરો: Android has removed AnkiDroid\'s %1$s permission due to app inactivity.\n\nYour data is safe and can be restored. It is located at\n%2$s\n\nSelect an option below to restore: Restore from AnkiWeb (recommended) Restore folder access (recommended) Restore folder access (advanced) Restore from .colpkg backup (advanced) - Create a new collection - The new collection will be deleted from your phone if you uninstall AnkiDroid + એક નવો સંગ્રહ બનાવો + જો તમે AnkiDroid ને અનઇન્સ્ટોલ કરશો તો તમારા ફોનમાંથી નવો સંગ્રહ કાઢી નાખવામાં આવશે - AnkiDroid needs some permissions to work - Storage access - Saves your collection in a safe place that will not be deleted if the app is uninstalled - All files access + AnkiDroid ને કામ કરવા માટે કેટલીક પરવાનગીઓની જરૂર છે + સ્ટોરેજ ઍક્સેસ + તમારા સંગ્રહને સુરક્ષિત જગ્યાએ સાચવે છે જે જો એપ્લિકેશન અનઇન્સ્ટોલ કરવામાં આવે તો કાઢી નાખવામાં આવશે નહીં + બધી ફાઇલો ઍક્સેસ Image Occlusion એકાઉન્ટ દૂર કરો diff --git a/AnkiDroid/src/main/res/values-th/01-core.xml b/AnkiDroid/src/main/res/values-th/01-core.xml index 4c758383eaa1..0bc87f7d83ea 100644 --- a/AnkiDroid/src/main/res/values-th/01-core.xml +++ b/AnkiDroid/src/main/res/values-th/01-core.xml @@ -60,13 +60,13 @@ ขยาย ซ่อน - %d minutes left + เหลืออีก %d นาที - %1$d hours %2$d left + เหลืออีก %1$d ชั่วโมง %2$d นาที - %1$d days %2$d left + เหลืออีก %1$d วัน %2$d ชั่วโมง ไม่มีคอเล็คชั่น เริ่มต้นเพิ่มการ์ดได้\nโดยการกดที่ไอคอน + @@ -88,7 +88,7 @@ เปลี่ยนชื่อสำรับ สร้างทางลัด ค้นหาการ์ด - Edit description + แก้ไขคำอธิบาย เพิ่ม เพิ่มโน้ต เชื่อมบัญชีผู้ใช้ @@ -109,41 +109,41 @@ ยกเลิกการทำเครื่องหมายโน้ต ตรวจสอบวิธีการออกเสียง สร้างกองใหม่ - Create filtered deck - AnkiDroid directory is inaccessible + สร้าง สำรับแบบกรอง + เข้าถึงที่เก็บข้อมูล AnkiDroid ไม่ได้ - Please grant AnkiDroid the ‘Storage’ permission to continue + กรุณาอนุญาติ AnkiDroid ให้เข้าถึง \'พื้นที่เก็บข้อมูล\' เพื่อดำเนินการต่อ Rebuilding filtered deck… Rebuild - Empty - Create subdeck - Emptying filtered deck… + ล้างสำรับ + สร้างสำรับย่อย + กำลังทำให้สำรับแบบกรองว่าง… Custom study session Rename the existing custom study deck first - Deck Search - This deck is empty - Deck Search - Invalid deck name - Congratulations! You have finished for now. - No cards are due yet + ค้นหาสำรับ + สำรับนี้ว่างเปล่า + ค้นหาสำรับ + ชื่อนี้ไม่สามารถตั้งให้สำรับได้ + ยินดีด้วย! คุณทบทวนเสร็จแล้วสำหรับตอนนี้ + ไม่มีบัตรคำที่ต้องทบทวนในตอนนี้ Device storage not mounted - Sync + การซิงค์ Migrate to scoped storage Do you want to cancel the sync? - Continue sync - Sync cancelled - Cancelling…\nThis may take some time. - Syncing media - Export deck - Nothing + ดำเนินการซิงค์ต่อไป + ยกเลิกการซิงค์เรียบร้อย + กำลังยกเลิกการซิงค์&…\nอาจจะต้องใช้เวลาสักนิดหน่อย + กำลังซิงค์มีเดีย + ส่งออกสำรับ + ไม่มี - Card types - Front template - Back template - Styling + ชนิดบัตรคำ + แม่แบบด้านหน้า + แม่แบบด้านหลัง + การตกแต่ง Card Browser Appearance Deck override Insert field diff --git a/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml b/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml index 70b7d31a2b59..01b2626d2a66 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml @@ -241,5 +241,5 @@ 图片遮挡 删除账户 - Instant card + 即时卡片 From ba546f229e960d161b03a27c21d88d85b4582a15 Mon Sep 17 00:00:00 2001 From: Ashish Yadav <48384865+criticalAY@users.noreply.github.com> Date: Tue, 14 May 2024 22:49:22 +0530 Subject: [PATCH 038/138] feature: Instant Note Editor to allow adding cloze card * Activity to support adding notes without opening AnkiDroid * Text surround helper to tap and turn to cloze * unitTest: InstantEdtitorViewModel unit test --- AnkiDroid/src/main/AndroidManifest.xml | 7 +- .../main/java/com/ichi2/anki/NoteEditor.kt | 3 +- .../InstantEditorViewModel.kt | 174 +++++++ .../InstantNoteEditorActivity.kt | 477 +++++++++++++++++- .../instantnoteeditor/TextSurroundHelper.kt | 149 ++++++ .../res/drawable/ic_round_open_in_new.xml | 22 + .../main/res/layout/instant_editor_dialog.xml | 135 +++++ .../layout/instant_editor_field_layout.xml | 36 ++ AnkiDroid/src/main/res/values/03-dialogs.xml | 6 + .../InstantEditorViewModelTest.kt | 110 ++++ 10 files changed, 1115 insertions(+), 4 deletions(-) create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantEditorViewModel.kt create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/TextSurroundHelper.kt create mode 100644 AnkiDroid/src/main/res/drawable/ic_round_open_in_new.xml create mode 100644 AnkiDroid/src/main/res/layout/instant_editor_dialog.xml create mode 100644 AnkiDroid/src/main/res/layout/instant_editor_field_layout.xml create mode 100644 AnkiDroid/src/test/java/com/ichi2/anki/instanteditor/InstantEditorViewModelTest.kt diff --git a/AnkiDroid/src/main/AndroidManifest.xml b/AnkiDroid/src/main/AndroidManifest.xml index c04c52b3d178..671c6791c63a 100644 --- a/AnkiDroid/src/main/AndroidManifest.xml +++ b/AnkiDroid/src/main/AndroidManifest.xml @@ -595,12 +595,17 @@ --> + + + + + diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt b/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt index e2b84e7a5008..274fbfb2df5f 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt @@ -517,7 +517,7 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags } CALLER_STUDYOPTIONS, CALLER_DECKPICKER, CALLER_REVIEWER_ADD, CALLER_CARDBROWSER_ADD, CALLER_NOTEEDITOR -> addNote = true - CALLER_NOTEEDITOR_INTENT_ADD -> { + CALLER_NOTEEDITOR_INTENT_ADD, INSTANT_NOTE_EDITOR -> { fetchIntentInformation(intent) if (sourceText == null) { finish() @@ -2458,6 +2458,7 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags const val RESULT_UPDATED_IO_NOTE = 11 const val CALLER_IMG_OCCLUSION = 12 const val CALLER_ADD_IMAGE = 13 + const val INSTANT_NOTE_EDITOR = 14 // preferences keys const val PREF_NOTE_EDITOR_SCROLL_TOOLBAR = "noteEditorScrollToolbar" diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantEditorViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantEditorViewModel.kt new file mode 100644 index 000000000000..8a790af81692 --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantEditorViewModel.kt @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2024 Ashish Yadav + * + * 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 . + */ + +package com.ichi2.anki.instantnoteeditor + +import android.content.Context +import androidx.annotation.VisibleForTesting +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.ichi2.anki.CollectionManager.withCol +import com.ichi2.anki.NoteFieldsCheckResult +import com.ichi2.anki.OnErrorListener +import com.ichi2.anki.R +import com.ichi2.anki.checkNoteFieldsResponse +import com.ichi2.anki.instantnoteeditor.InstantNoteEditorActivity.DialogType +import com.ichi2.anki.utils.ext.getAllClozeTextFields +import com.ichi2.libanki.DeckId +import com.ichi2.libanki.Decks +import com.ichi2.libanki.Note +import com.ichi2.libanki.NotetypeJson +import com.ichi2.libanki.undoableOp +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch +import timber.log.Timber + +/** + * ViewModel for managing instant note editing functionality. + * This ViewModel provides methods for handling note editing operations and + * managing the state related to instant note editing. + */ +class InstantEditorViewModel : ViewModel(), OnErrorListener { + override val onError = MutableSharedFlow() + + /** Errors or Warnings related to the edit fields that might occur when trying to save note */ + val instantEditorError = MutableSharedFlow() + + /** + * Gets the current editor note. + */ + @VisibleForTesting + lateinit var editorNote: Note + + private val _currentlySelectedNotetype = MutableLiveData() + + /** + * Representing the currently selected note type. + * + * @see NotetypeJson + */ + val currentlySelectedNotetype: LiveData get() = _currentlySelectedNotetype + + var deckId: DeckId? = null + + private val _dialogType = MutableStateFlow(null) + + /** Representing the type of dialog to be displayed. + * @see DialogType*/ + val dialogType: StateFlow get() = _dialogType + + init { + viewModelScope.launch { + // setup the deck Id + withCol { config.get(Decks.CURRENT_DECK) ?: 1L }.let { did -> + deckId = did + } + + // setup the note type + // TODO: Use did here + val noteType = withCol { notetypes.all().firstOrNull { it.isCloze } } + if (noteType == null) { + _dialogType.emit(DialogType.NO_CLOZE_NOTE_TYPES_DIALOG) + return@launch + } + + @Suppress("RedundantRequireNotNullCall") // postValue lint requires this + val clozeNoteType = requireNotNull(noteType) + Timber.d("Changing to cloze type note") + _currentlySelectedNotetype.postValue(clozeNoteType) + Timber.i("Using note type '%d", clozeNoteType.id) + editorNote = withCol { Note.fromNotetypeId(clozeNoteType.id) } + + _dialogType.emit(DialogType.SHOW_EDITOR_DIALOG) + } + } + + /** Update the deck id when changed from deck spinner **/ + fun setDeckId(deckId: DeckId) { + this.deckId = deckId + } + + /** + * Checks the note fields and calls [saveNote] if all fields are valid. + * If [skipClozeCheck] is set to true, the cloze field check is skipped. + * + * @param context The context used to retrieve localized error messages. + * @param skipClozeCheck Indicates whether to skip the cloze field check. + * @return A [SaveNoteResult] indicating the outcome of the operation. + */ + suspend fun checkAndSaveNote( + context: Context, + skipClozeCheck: Boolean = false + ): SaveNoteResult { + if (skipClozeCheck) { + return saveNote() + } + + val note = editorNote + val result = checkNoteFieldsResponse(note) + if (result is NoteFieldsCheckResult.Failure) { + val errorMessage = result.getLocalizedMessage(context) + return SaveNoteResult.Warning(errorMessage) + } + Timber.d("Note fields check successful, saving note") + instantEditorError.emit(null) + return saveNote() + } + + /** Adds the note to the collection. + * @return If the operation is successful, returns [SaveNoteResult.Success], + * otherwise returns [SaveNoteResult.Failure]. + */ + private suspend fun saveNote(): SaveNoteResult { + return try { + editorNote.notetype.put("did", deckId) + + val note = editorNote + val deckId = deckId ?: return SaveNoteResult.Failure() + + Timber.d("Note and deck id not null, adding note") + undoableOp { addNote(note, deckId) } + + SaveNoteResult.Success + } catch (e: Exception) { + Timber.w(e, "Error saving note") + SaveNoteResult.Failure() + } + } + + fun getClozeFields(): List { + return editorNote.notetype.getAllClozeTextFields() + } +} + +/** + * Represents the result of saving a note operation. + */ +sealed class SaveNoteResult { + data object Success : SaveNoteResult() + + data class Failure(val message: String? = null) : SaveNoteResult() { + fun getErrorMessage(context: Context) = + message ?: context.getString(R.string.something_wrong) + } + + data class Warning(val message: String?) : SaveNoteResult() +} diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt index b89a8e60d326..39ad77f5036b 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt @@ -17,17 +17,72 @@ package com.ichi2.anki.instantnoteeditor +import android.app.Activity +import android.content.Context +import android.content.Intent import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher +import android.view.ActionMode +import android.view.LayoutInflater +import android.view.View +import android.view.inputmethod.InputMethodManager +import android.widget.EditText +import android.widget.LinearLayout import androidx.activity.enableEdgeToEdge +import androidx.activity.viewModels +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.flowWithLifecycle +import androidx.lifecycle.lifecycleScope +import com.google.android.material.button.MaterialButton +import com.google.android.material.materialswitch.MaterialSwitch +import com.google.android.material.textfield.TextInputEditText +import com.google.android.material.textfield.TextInputLayout 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.launchCatchingTask +import com.ichi2.anki.servicelayer.NoteService +import com.ichi2.anki.showThemedToast +import com.ichi2.anki.withProgress +import com.ichi2.libanki.NotetypeJson import com.ichi2.themes.setTransparentBackground +import com.ichi2.ui.FixedTextView +import com.ichi2.utils.jsonObjectIterable +import com.ichi2.utils.message +import com.ichi2.utils.negativeButton +import com.ichi2.utils.positiveButton +import com.ichi2.utils.show +import com.ichi2.utils.title +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch +import timber.log.Timber +import kotlin.math.max /** * Single instance Activity for instantly editing and adding cloze card/s without actually opening the app, * uses a custom dialog layout and a transparent activity theme to achieve the functionality. **/ -class InstantNoteEditorActivity : AnkiActivity() { +class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelectionListener { + private val viewModel: InstantEditorViewModel by viewModels() + + private var deckSpinnerSelection: DeckSpinnerSelection? = null + + private var dialogView: View? = null + + private var sharedIntentText: IntentSharedText? = null + + private lateinit var singleTapSwitch: MaterialSwitch + private var editFieldsLayout: LinearLayout? = null + private lateinit var clozeEditTextField: TextInputEditText + private lateinit var warningTextField: FixedTextView + private lateinit var instantAlertDialog: AlertDialog override fun onCreate(savedInstanceState: Bundle?) { if (showedActivityFailedScreen(savedInstanceState)) { @@ -39,7 +94,425 @@ class InstantNoteEditorActivity : AnkiActivity() { } setTransparentBackground() enableEdgeToEdge() + setContentView(R.layout.activity_instant_note_editor) - onDestroy() + + if (Intent.ACTION_SEND == intent.action && intent.type != null && "text/plain" == intent.type) { + handleSharedText(intent) + } + + setupErrorListeners() + prepareEditorDialog() + } + + private fun prepareEditorDialog() = lifecycleScope.launch { + Timber.d("Checking for cloze note type") + + viewModel.dialogType.collect { dialogType -> + dialogType?.let { dialog -> + when (dialog) { + DialogType.NO_CLOZE_NOTE_TYPES_DIALOG -> { + Timber.d("Showing no cloze note type dialog") + noClozeNoteTypesFoundDialog() + } + + DialogType.SHOW_EDITOR_DIALOG -> { + Timber.d("Showing editor dialog") + showEditorDialog() + } + } + } + } + } + + /** Setup the deck spinner and custom editor dialog layout **/ + private fun showEditorDialog() { + showDialog() + deckSpinnerSelection = DeckSpinnerSelection( + dialogView!!.context as AppCompatActivity, + dialogView!!.findViewById(R.id.note_deck_spinner), + showAllDecks = false, + alwaysShowDefault = true, + showFilteredDecks = false + ).apply { + initializeNoteEditorDeckSpinner(getColUnsafe) + launchCatchingTask { + viewModel.deckId?.let { selectDeckById(it, true) } + } + } + } + + /** Handles the shared text received through an Intent. **/ + private fun handleSharedText(receivedIntent: Intent) { + val sharedText = receivedIntent.getStringExtra(Intent.EXTRA_TEXT) ?: return + sharedIntentText = IntentSharedText(sharedText) + } + + private fun openNoteEditor() { + val sharedText = intent.getStringExtra(Intent.EXTRA_TEXT) + val noteEditorIntent = Intent(this, NoteEditor::class.java).apply { + putExtra(NoteEditor.EXTRA_CALLER, NoteEditor.INSTANT_NOTE_EDITOR) + putExtra(Intent.EXTRA_TEXT, sharedText) + } + startActivity(noteEditorIntent) + finish() + } + + fun showDialog() { + Timber.d("Showing Instant Note Editor dialog") + val dialogView = layoutInflater.inflate(R.layout.instant_editor_dialog, null).also { dv -> + dialogView = dv + } + editFieldsLayout = dialogView.findViewById(R.id.editor_fields_layout) + singleTapSwitch = dialogView.findViewById(R.id.switch_single_tap_cloze) + dialogView.findViewById(R.id.open_note_editor)?.setOnClickListener { + openNoteEditor() + } + warningTextField = dialogView.findViewById(R.id.warning_text) + dialogView.findViewById(R.id.increment_cloze_button)?.setOnClickListener { + currentClozeNumber++ + Timber.d("Incrementing cloze number: $currentClozeNumber") + } + + val editFields = createEditFields(this, viewModel.currentlySelectedNotetype.value) + + Timber.d("Adding edit text fields to the dialog") + for (editField in editFields) { + editFieldsLayout?.addView(editField) + } + + instantAlertDialog = AlertDialog.Builder(this).show { + setView(dialogView) + val spinner = dialogView.findViewById(R.id.spinner_layout) + spinner.setOnClickListener { + launchCatchingTask { deckSpinnerSelection!!.displayDeckSelectionDialog() } + } + dialogView.findViewById(R.id.action_save_note)?.setOnClickListener { + Timber.d("Save note button pressed") + checkAndSave() + } + setOnDismissListener { + finish() + } + } + } + + private fun createEditFields( + context: Context, + notetypeJson: NotetypeJson? + ): List { + val editLines: MutableList = mutableListOf() + + val clozeFields = viewModel.getClozeFields() + var clozeFieldsSet = false + + for (i in notetypeJson?.flds!!.jsonObjectIterable()) { + // Inflate the existing layout + val inflater = LayoutInflater.from(context) + val existingLayout = inflater.inflate(R.layout.instant_editor_field_layout, null) + + val textInputLayout = + existingLayout.findViewById(R.id.edit_text_layout) + val textInputEditText = + existingLayout.findViewById(R.id.edit_field_text) + + val name = i.getString("name") + textInputLayout.hint = name + + Timber.d("Populating the cloze edit text fields") + // Anki allows multiple cloze fields, we pick the first field + if (clozeFields.contains(name) && !clozeFieldsSet) { + setupClozeFields(textInputEditText) + clozeFieldsSet = true + } + + editLines.add(existingLayout) + } + return editLines + } + + /** Sets the copied text to the cloze field and enable the single tap gesture for that field**/ + private fun setupClozeFields(textBox: TextInputEditText) { + clozeEditTextField = textBox + textBox.setText(sharedIntentText?.sharedTextString) + val gestureHelper = EditTextGestureHelper( + textBox, + EditTextGestureState(singleTapSwitch.isChecked) + ) + + enableErrorMessage() + + setActionModeCallback(textBox) + + singleTapSwitch.setOnCheckedChangeListener { _, check -> + gestureHelper.toggleGestureState() + if (check) { + hideKeyboard() + } + } + } + + private fun hideKeyboard() { + val inputMethodManager = + this.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager + inputMethodManager.hideSoftInputFromWindow(clozeEditTextField.windowToken, 0) + } + + /** Set the error message to null when the text is changed in the TextInputEditText **/ + private fun enableErrorMessage() { + clozeEditTextField.addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { + // No action needed + } + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { + lifecycleScope.launch { + viewModel.instantEditorError.emit(null) + } + } + + override fun afterTextChanged(s: Editable?) { + // No action needed + } + }) + } + + /** + * Checks if the fields are not empty and contain cloze deletions, + * retrieves the field content, and saves the note + */ + private fun checkAndSave() { + getFieldValues() + + lifecycleScope.launch { + val result = withProgress(resources.getString(R.string.saving_facts)) { + viewModel.checkAndSaveNote(this@InstantNoteEditorActivity) + } + handleSaveNoteResult(result) + } + } + + private fun handleSaveNoteResult(result: SaveNoteResult) { + when (result) { + is SaveNoteResult.Failure -> { + Timber.d("Failed to save note") + savingErrorDialog(result.getErrorMessage(this)) + } + + SaveNoteResult.Success -> { + currentClozeNumber = 0 + // Don't show snackbar to avoid blocking parent app + showThemedToast(this@InstantNoteEditorActivity, TR.addingAdded(), true) + instantAlertDialog.dismiss() + } + + is SaveNoteResult.Warning -> { + Timber.d("Showing warning to the user") + lifecycleScope.launch { viewModel.instantEditorError.emit(result.message) } + } + } + } + + override fun onDestroy() { + super.onDestroy() + currentClozeNumber = 0 + } + + /** Gets the field content from the editor **/ + private fun getFieldValues() { + val editTextValues = mutableListOf() + + editFieldsLayout?.let { layout -> + for (i in 0 until layout.childCount) { + val childView = layout.getChildAt(i) + + if (childView is TextInputLayout) { + val text = extractTextFromInputField(childView) + Timber.d("String values in field are $text") + editTextValues.add(text) + + updateFields(i, childView.findViewById(R.id.edit_field_text)) + } + } + } + } + + private fun extractTextFromInputField(textInputLayout: TextInputLayout): String { + val textInputEditText = + textInputLayout.findViewById(R.id.edit_field_text) + return textInputEditText?.text?.toString() ?: "" + } + + private fun updateFields(index: Int, field: TextInputEditText?) { + val fieldContent = field!!.text?.toString() ?: "" + val correctedFieldContent = NoteService.convertToHtmlNewline( + fieldContent, + false + ) + + val note = viewModel.editorNote + if (note.values()[index] != correctedFieldContent) { + note.values()[index] = correctedFieldContent + } + } + + /** Show a dialog when there is no cloze note type is found, allowing user either to cancel or to open + * AnkiDroid Note Editor **/ + private fun noClozeNoteTypesFoundDialog() { + AlertDialog.Builder(this).show { + title(R.string.cloze_note_required) + message(R.string.cloze_not_found_message) + positiveButton(R.string.open) { + openNoteEditor() + } + negativeButton(R.string.dialog_cancel) { + finish() + } + } + } + + private fun setupErrorListeners() { + viewModel.onError.flowWithLifecycle(lifecycle).onEach { errorMessage -> + AlertDialog.Builder(this).setTitle(R.string.vague_error).setMessage(errorMessage) + .show() + }.launchIn(lifecycleScope) + + viewModel.instantEditorError.onEach { errorMessage -> + when (errorMessage) { + null -> { + warningTextField.visibility = View.INVISIBLE + } + + TR.addingYouHaveAClozeDeletionNote() -> { + noClozeDialog(errorMessage) + } + + else -> { + warningTextField.visibility = View.VISIBLE + warningTextField.text = errorMessage + } + } + }.launchIn(lifecycleScope) + } + + /** In case saving the note fails we, want to allow user to cancel and try again, or exist the activity **/ + private fun savingErrorDialog(message: String) { + AlertDialog.Builder(this).show { + message(text = message) + positiveButton(R.string.dialog_cancel) { + instantAlertDialog.dismiss() + } + negativeButton(R.string.try_again) + } + } + + /** Warns the user for no cloze in the cloze field, and provide the choice to proceed or + * to abort save and go back to the editor **/ + private fun noClozeDialog(errorMessage: String) { + AlertDialog.Builder(this).show { + message(text = errorMessage) + positiveButton(text = TR.actionsSave()) { + lifecycleScope.launch { + val result = withProgress(resources.getString(R.string.saving_facts)) { + viewModel.checkAndSaveNote(this@InstantNoteEditorActivity, true) + } + handleSaveNoteResult(result) + } + } + negativeButton(R.string.dialog_cancel) + } + } + + override fun onDeckSelected(deck: DeckSelectionDialog.SelectableDeck?) { + if (deck == null) { + return + } + viewModel.setDeckId(deck.deckId) + // this is called because DeckSpinnerSelection.onDeckAdded doesn't update the list + deckSpinnerSelection!!.initializeNoteEditorDeckSpinner(getColUnsafe) + launchCatchingTask { + viewModel.deckId?.let { deckSpinnerSelection!!.selectDeckById(it, false) } + } + } + + private fun setActionModeCallback(textBox: TextInputEditText) { + val clozeMenuId = View.generateViewId() + textBox.customSelectionActionModeCallback = getActionModeCallback(textBox, clozeMenuId) + textBox.customInsertionActionModeCallback = getActionModeCallback(textBox, clozeMenuId) + getActionModeCallback(textBox, clozeMenuId) + } + + private fun getActionModeCallback( + textBox: TextInputEditText, + clozeMenuId: Int + ): ActionMode.Callback { + return CustomActionModeCallback( + // we always have cloze type notes here + isClozeType = true, + getString(R.string.multimedia_editor_popup_cloze), + clozeMenuId, + onActionItemSelected = { mode, item -> + val itemId = item.itemId + if (itemId == clozeMenuId) { + val selectedText = textBox.text?.substring( + textBox.selectionStart, + textBox.selectionEnd + ) ?: "" + convertSelectedTextToCloze( + textBox, + selectedText, + max(currentClozeNumber, 1) + ) + + mode.finish() + true + } else { + false + } + } + ) + } + + private fun convertSelectedTextToCloze( + textBox: EditText, + word: String, + incrementNumber: Int + ) { + val text = textBox.text.toString() + val selectionStart = textBox.selectionStart + + val start = text.indexOf(word, selectionStart - word.length) + val end = start + word.length + + if (start != -1 && end != -1) { + val newText = + text.substring(0, start) + "{{c$incrementNumber::$word}}" + text.substring(end) + + textBox.setText(newText) + textBox.setSelection(start + "{{c$incrementNumber::".length) + } + } + + /** + * Enum class that represent the dialog that can be shown when the InstantEditor is initialized + * **/ + enum class DialogType { + /** Indicates that no cloze note types were found. **/ + NO_CLOZE_NOTE_TYPES_DIALOG, + + /** Indicates that the editor dialog should be shown. **/ + SHOW_EDITOR_DIALOG + } + + companion object { + /** Allows to keep track of the current cloze number, reset to 0 when activity is destroyed **/ + var currentClozeNumber: Int = 0 } } + +/** + * Encapsulates the shared text data received through Intent + **/ +data class IntentSharedText( + val sharedTextString: String +) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/TextSurroundHelper.kt b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/TextSurroundHelper.kt new file mode 100644 index 000000000000..1f0e853d7de1 --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/TextSurroundHelper.kt @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2024 Ashish Yadav + * + * 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 . + */ + +package com.ichi2.anki.instantnoteeditor + +import android.view.GestureDetector +import android.view.MotionEvent +import android.widget.EditText +import kotlin.math.max + +/** + * Represents the state of EditText gesture recognition + * + * This data class holds states of gesture recognition for an EditText, + * allowing for clear and concise representation of its state. + */ +data class EditTextGestureState(val isEnabled: Boolean) + +/** + * Helper class to handle gesture recognition for EditText + * + * Facilitates the management of gesture recognition functionality + * for an EditText component. It allows enabling or disabling gesture detection + * based on the provided state, and provides methods for toggling the gesture state. + */ +class EditTextGestureHelper(private val editText: EditText, initialState: EditTextGestureState) { + private var currentState: EditTextGestureState = initialState + + init { + applyState(currentState) + } + + private fun applyState(state: EditTextGestureState) { + if (state.isEnabled) { + enableGesture() + } else { + disableGesture() + } + } + + private fun setupGestureDetection() { + val gestureDetector = + GestureDetector( + editText.context, + object : GestureDetector.SimpleOnGestureListener() { + override fun onSingleTapConfirmed(e: MotionEvent): Boolean { + handleSingleTap(e) + return super.onSingleTapConfirmed(e) + } + } + ) + + editText.setOnTouchListener { _, event -> + gestureDetector.onTouchEvent(event) + editText.onTouchEvent(event) + true + } + + editText.apply { + showSoftInputOnFocus = false + isFocusable = false + isCursorVisible = false + isFocusableInTouchMode = true + } + } + + private fun handleSingleTap(event: MotionEvent) { + singleTap(editText, event) + } + + /** + * Handles a single tap event on the EditText. + * This method is responsible for detecting the tapped word, surrounding it with cloze brackets, + * and updating the EditText with the modified text. + * + * @param editText The EditText where the tap event occurred. + * @param event The MotionEvent representing the tap event. + */ + private fun singleTap(editText: EditText, event: MotionEvent) { + val layout = editText.layout + val x = event.x.toInt() + val y = event.y.toInt() + + val line = layout.getLineForVertical(y) + val offset = layout.getOffsetForHorizontal(line, x.toFloat()) + + val text = editText.text.toString() + val start = findWordStart(text, offset) + val end = findWordEnd(text, offset) + + val selectedWord = text.substring(start, end) + InstantNoteEditorActivity.currentClozeNumber = max(InstantNoteEditorActivity.currentClozeNumber, 1) + val newText = buildString { + append(text.substring(0, start)) + append("{{c${InstantNoteEditorActivity.currentClozeNumber}::$selectedWord}}") + append(text.substring(end)) + } + editText.setText(newText) + } + + private fun findWordStart(text: String, offset: Int): Int { + var start = offset + while (start > 0 && !text[start - 1].isWhitespace()) { + start-- + } + return start + } + + private fun findWordEnd(text: String, offset: Int): Int { + var end = offset + while (end < text.length && !text[end].isWhitespace()) { + end++ + } + return end + } + + private fun enableGesture() { + setupGestureDetection() + } + + private fun disableGesture() { + editText.apply { + setOnTouchListener(null) + isFocusable = true + isFocusableInTouchMode = true + showSoftInputOnFocus = true + isCursorVisible = true + } + } + + fun toggleGestureState() { + currentState = EditTextGestureState(!currentState.isEnabled) + applyState(currentState) + } +} diff --git a/AnkiDroid/src/main/res/drawable/ic_round_open_in_new.xml b/AnkiDroid/src/main/res/drawable/ic_round_open_in_new.xml new file mode 100644 index 000000000000..88a65a8ade78 --- /dev/null +++ b/AnkiDroid/src/main/res/drawable/ic_round_open_in_new.xml @@ -0,0 +1,22 @@ + + + + + + + diff --git a/AnkiDroid/src/main/res/layout/instant_editor_dialog.xml b/AnkiDroid/src/main/res/layout/instant_editor_dialog.xml new file mode 100644 index 000000000000..9d461c66e8b2 --- /dev/null +++ b/AnkiDroid/src/main/res/layout/instant_editor_dialog.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AnkiDroid/src/main/res/layout/instant_editor_field_layout.xml b/AnkiDroid/src/main/res/layout/instant_editor_field_layout.xml new file mode 100644 index 000000000000..c860f9b785b9 --- /dev/null +++ b/AnkiDroid/src/main/res/layout/instant_editor_field_layout.xml @@ -0,0 +1,36 @@ + + + + + \ No newline at end of file diff --git a/AnkiDroid/src/main/res/values/03-dialogs.xml b/AnkiDroid/src/main/res/values/03-dialogs.xml index 9f36df404b36..1878f2b30b0b 100644 --- a/AnkiDroid/src/main/res/values/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values/03-dialogs.xml @@ -271,4 +271,10 @@ also changes the interval of the card" From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze + diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/instanteditor/InstantEditorViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/instanteditor/InstantEditorViewModelTest.kt new file mode 100644 index 000000000000..3c438741b5a0 --- /dev/null +++ b/AnkiDroid/src/test/java/com/ichi2/anki/instanteditor/InstantEditorViewModelTest.kt @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2024 Ashish Yadav + * + * 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 . + */ + +package com.ichi2.anki.instanteditor + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.ichi2.anki.CollectionManager +import com.ichi2.anki.RobolectricTest +import com.ichi2.anki.instantnoteeditor.InstantEditorViewModel +import com.ichi2.anki.instantnoteeditor.InstantNoteEditorActivity +import com.ichi2.anki.instantnoteeditor.SaveNoteResult +import com.ichi2.libanki.removeNotetype +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class InstantEditorViewModelTest : RobolectricTest() { + + @Test + fun testSetUpNoteType_with_Cloze_NoteType() = runViewModelTest { + assertEquals(InstantNoteEditorActivity.DialogType.SHOW_EDITOR_DIALOG, dialogType.value) + } + + @Test + fun testSetUpNoteType_with_NoCloze_NoteType() = runViewModelTest { + val noteTypes = col.notetypes.all().filter { it.isCloze } + + for (note in noteTypes) { + col.backend.removeNotetype(note.id) + } + + waitForAsyncTasksToComplete() + + // Reinitialize the viewModel + runViewModelTest({ InstantEditorViewModel() }) { + assertEquals( + InstantNoteEditorActivity.DialogType.NO_CLOZE_NOTE_TYPES_DIALOG, + dialogType.value + ) + } + } + + @Test + fun testSavingNoteWithNoCloze() = runViewModelTest { + editorNote.setField(0, "Hello") + val result = checkAndSaveNote(targetContext) + + assertEquals(CollectionManager.TR.addingYouHaveAClozeDeletionNote(), saveNoteResult(result)) + } + + @Test + fun testSavingNoteWithEmptyFields() = runViewModelTest { + editorNote.setField(0, "{{c1::Hello}}") + + val result = checkAndSaveNote(targetContext) + + assertEquals("Success", saveNoteResult(result)) + } + + @Test + fun testSavingNoteWithClozeFields() = runViewModelTest { + val result = checkAndSaveNote(targetContext) + + assertEquals(CollectionManager.TR.addingTheFirstFieldIsEmpty(), saveNoteResult(result)) + } + + @Test + fun testCheckAndSaveNote_NullEditorNote_ReturnsFailure() = runViewModelTest { + val result = checkAndSaveNote(targetContext) + + assertTrue(result is SaveNoteResult.Warning) + } + + private fun runViewModelTest( + initViewModel: () -> InstantEditorViewModel = { InstantEditorViewModel() }, + testBody: suspend InstantEditorViewModel.() -> Unit + ) = runTest { + val viewModel = initViewModel() + testBody(viewModel) + } + + private fun saveNoteResult(result: SaveNoteResult): String? { + return when (result) { + is SaveNoteResult.Failure -> result.message + + SaveNoteResult.Success -> { + // It doesn't return a string in case of success hence we mimic that that the check was successful + "Success" + } + + is SaveNoteResult.Warning -> result.message + } + } +} From 1481492b59930b8768d1cbc36d332e59babb7d83 Mon Sep 17 00:00:00 2001 From: Ashish Yadav <48384865+criticalAY@users.noreply.github.com> Date: Sat, 1 Jun 2024 22:33:20 +0530 Subject: [PATCH 039/138] set the activity to dev only --- AnkiDroid/src/main/AndroidManifest.xml | 13 +++++++------ .../instantnoteeditor/InstantNoteEditorActivity.kt | 13 ++++++++----- .../ichi2/anki/preferences/DevOptionsFragment.kt | 10 ++++++++++ AnkiDroid/src/main/res/values/constants.xml | 3 +++ AnkiDroid/src/main/res/values/preferences.xml | 3 +++ .../src/main/res/xml/preferences_dev_options.xml | 7 +++++++ 6 files changed, 38 insertions(+), 11 deletions(-) diff --git a/AnkiDroid/src/main/AndroidManifest.xml b/AnkiDroid/src/main/AndroidManifest.xml index 671c6791c63a..77d9594bccf3 100644 --- a/AnkiDroid/src/main/AndroidManifest.xml +++ b/AnkiDroid/src/main/AndroidManifest.xml @@ -593,19 +593,20 @@ Task affinity allows us to separate the activity allowing us to define that an activity belongs to a different task, it ensures that the activity does not interfere with other tasks in our application. --> + - - - - - + + + + + diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt index 39ad77f5036b..edbde5c7ac0f 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt @@ -97,9 +97,11 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect setContentView(R.layout.activity_instant_note_editor) - if (Intent.ACTION_SEND == intent.action && intent.type != null && "text/plain" == intent.type) { - handleSharedText(intent) - } + // TODO: enable it back when done and remove the direct call +// if (Intent.ACTION_SEND == intent.action && intent.type != null && "text/plain" == intent.type) { +// handleSharedText(intent) +// } + handleSharedText(intent) setupErrorListeners() prepareEditorDialog() @@ -144,8 +146,9 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect /** Handles the shared text received through an Intent. **/ private fun handleSharedText(receivedIntent: Intent) { - val sharedText = receivedIntent.getStringExtra(Intent.EXTRA_TEXT) ?: return - sharedIntentText = IntentSharedText(sharedText) + val sharedText = receivedIntent.getStringExtra(Intent.EXTRA_TEXT) ?: intent.getStringExtra("extra_text_key") + + sharedIntentText = IntentSharedText(sharedText!!) } private fun openNoteEditor() { diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/preferences/DevOptionsFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/preferences/DevOptionsFragment.kt index b5fa1f50e0e3..3b6fb58e2f0c 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/preferences/DevOptionsFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/preferences/DevOptionsFragment.kt @@ -16,11 +16,13 @@ package com.ichi2.anki.preferences import android.content.Context +import android.content.Intent import androidx.appcompat.app.AlertDialog import androidx.preference.Preference import androidx.preference.SwitchPreferenceCompat import com.ichi2.anki.* import com.ichi2.anki.analytics.UsageAnalytics +import com.ichi2.anki.instantnoteeditor.InstantNoteEditorActivity import com.ichi2.anki.snackbar.showSnackbar import com.ichi2.preferences.IncrementerNumberRangePreferenceCompat import com.ichi2.utils.show @@ -81,6 +83,14 @@ class DevOptionsFragment : SettingsFragment() { OnboardingUtils.reset(requireContext()) false } + // Instant Editor + requirePreference(R.string.pref_open_instant_editor).setOnPreferenceClickListener { + val intent = Intent(activity, InstantNoteEditorActivity::class.java).apply { + putExtra("extra_text_key", "Hello developer, this a test sentence. You can test turning text to cloze here") + } + startActivity(intent) + false + } val sizePreference = requirePreference(getString(R.string.pref_fill_collection_size_file_key)) val numberOfFilePreference = requirePreference(getString(R.string.pref_fill_collection_number_file_key)) diff --git a/AnkiDroid/src/main/res/values/constants.xml b/AnkiDroid/src/main/res/values/constants.xml index 73f1f5ae8df1..c1d48a875fa0 100644 --- a/AnkiDroid/src/main/res/values/constants.xml +++ b/AnkiDroid/src/main/res/values/constants.xml @@ -298,4 +298,7 @@ Show onboarding walkthrough Display feature tutorial to learn more about the app Show all tutorials again + + + Open Instant Editor diff --git a/AnkiDroid/src/main/res/values/preferences.xml b/AnkiDroid/src/main/res/values/preferences.xml index 7f5730464c07..a6ebc9475561 100644 --- a/AnkiDroid/src/main/res/values/preferences.xml +++ b/AnkiDroid/src/main/res/values/preferences.xml @@ -194,4 +194,7 @@ daily_backups_to_keep weekly_backups_to_keep monthly_backups_to_keep + + + openInstantEditor \ No newline at end of file diff --git a/AnkiDroid/src/main/res/xml/preferences_dev_options.xml b/AnkiDroid/src/main/res/xml/preferences_dev_options.xml index 7a3248cc460e..f1249b234cbe 100644 --- a/AnkiDroid/src/main/res/xml/preferences_dev_options.xml +++ b/AnkiDroid/src/main/res/xml/preferences_dev_options.xml @@ -61,6 +61,13 @@ android:title="@string/reset_onboarding" android:summary="@string/reset_onboarding_desc" android:key="@string/pref_reset_onboarding_key"/> + + From dfe33b6b79600a36fa024ccbeb1501133bffa927 Mon Sep 17 00:00:00 2001 From: Ashish Yadav <48384865+criticalAY@users.noreply.github.com> Date: Sun, 2 Jun 2024 13:28:57 +0530 Subject: [PATCH 040/138] refactor: activity to use viewModel to set warning * added TODOs to the viewModel and activity --- .../InstantEditorViewModel.kt | 44 +++++++++++++++++++ .../InstantNoteEditorActivity.kt | 37 ++++++++-------- 2 files changed, 62 insertions(+), 19 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantEditorViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantEditorViewModel.kt index 8a790af81692..3980c999ef2f 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantEditorViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantEditorViewModel.kt @@ -114,6 +114,7 @@ class InstantEditorViewModel : ViewModel(), OnErrorListener { * @param skipClozeCheck Indicates whether to skip the cloze field check. * @return A [SaveNoteResult] indicating the outcome of the operation. */ + // TODO: remove context from here suspend fun checkAndSaveNote( context: Context, skipClozeCheck: Boolean = false @@ -154,21 +155,64 @@ class InstantEditorViewModel : ViewModel(), OnErrorListener { } } + /** + * Retrieves all cloze text fields from the current editor note's note type. + * + * This method accesses the `editorNote` property to fetch its associated note type + * and then retrieves all cloze text fields using the [getAllClozeTextFields] method. + * + * @return A list of strings representing the cloze text fields in the current editor note's note type. + */ fun getClozeFields(): List { return editorNote.notetype.getAllClozeTextFields() } + + /** + * Set the warning message to be displayed in editor dialog + */ + fun setWarningMessage(message: String?) { + viewModelScope.launch { + instantEditorError.emit(message) + } + } } /** * Represents the result of saving a note operation. + * Has three possible outcomes: `Success`, `Failure`, and `Warning`. */ sealed class SaveNoteResult { + /** + * Indicates that the save note operation was successful. + */ data object Success : SaveNoteResult() + /** + * Indicates that the save note operation failed. + * + * @property message An optional message describing the reason for the failure. + */ data class Failure(val message: String? = null) : SaveNoteResult() { + + /** + * Retrieves the error message associated with this failure. + * + * If a message is provided, it returns that message. Otherwise, it returns a default + * error message from the context's resources. + * + * @param context The context used to retrieve the default error message string. + * @return The error message. + */ fun getErrorMessage(context: Context) = message ?: context.getString(R.string.something_wrong) } + /** + * Indicates that the save note operation completed with a warning. + * + * Example, when user tries to save cloze field with no cloze + * + * @property message A message describing the warning. + */ data class Warning(val message: String?) : SaveNoteResult() } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt index edbde5c7ac0f..affbcae0e864 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt @@ -128,6 +128,7 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect } /** Setup the deck spinner and custom editor dialog layout **/ + // TODO: subscribe to the flow of deckId to change the control value private fun showEditorDialog() { showDialog() deckSpinnerSelection = DeckSpinnerSelection( @@ -269,9 +270,7 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { - lifecycleScope.launch { - viewModel.instantEditorError.emit(null) - } + viewModel.setWarningMessage(null) } override fun afterTextChanged(s: Editable?) { @@ -285,14 +284,9 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect * retrieves the field content, and saves the note */ private fun checkAndSave() { - getFieldValues() + extractFieldValues() - lifecycleScope.launch { - val result = withProgress(resources.getString(R.string.saving_facts)) { - viewModel.checkAndSaveNote(this@InstantNoteEditorActivity) - } - handleSaveNoteResult(result) - } + saveNoteWithProgress(skipClozeCheck = false) } private fun handleSaveNoteResult(result: SaveNoteResult) { @@ -311,7 +305,7 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect is SaveNoteResult.Warning -> { Timber.d("Showing warning to the user") - lifecycleScope.launch { viewModel.instantEditorError.emit(result.message) } + viewModel.setWarningMessage(result.message) } } } @@ -321,8 +315,8 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect currentClozeNumber = 0 } - /** Gets the field content from the editor **/ - private fun getFieldValues() { + /** Gets the field content from the editor, and updates the Note **/ + private fun extractFieldValues() { val editTextValues = mutableListOf() editFieldsLayout?.let { layout -> @@ -415,17 +409,21 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect AlertDialog.Builder(this).show { message(text = errorMessage) positiveButton(text = TR.actionsSave()) { - lifecycleScope.launch { - val result = withProgress(resources.getString(R.string.saving_facts)) { - viewModel.checkAndSaveNote(this@InstantNoteEditorActivity, true) - } - handleSaveNoteResult(result) - } + saveNoteWithProgress(skipClozeCheck = true) } negativeButton(R.string.dialog_cancel) } } + private fun saveNoteWithProgress(skipClozeCheck: Boolean) { + lifecycleScope.launch { + val result = withProgress(resources.getString(R.string.saving_facts)) { + viewModel.checkAndSaveNote(this@InstantNoteEditorActivity, skipClozeCheck = skipClozeCheck) + } + handleSaveNoteResult(result) + } + } + override fun onDeckSelected(deck: DeckSelectionDialog.SelectableDeck?) { if (deck == null) { return @@ -508,6 +506,7 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect } companion object { + // TODO: Should not be global /** Allows to keep track of the current cloze number, reset to 0 when activity is destroyed **/ var currentClozeNumber: Int = 0 } From 9c949d616e900eff8615731eff6955dfe47c85e2 Mon Sep 17 00:00:00 2001 From: "sargamgayatri0803@gmail.com" Date: Mon, 3 Jun 2024 22:19:22 +0530 Subject: [PATCH 041/138] focus keyboard on RenameCardTemplateDialog --- .../java/com/ichi2/anki/notetype/RenameCardTemplateDialog.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/notetype/RenameCardTemplateDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/notetype/RenameCardTemplateDialog.kt index 1be569678c41..5eb1fe270c13 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/notetype/RenameCardTemplateDialog.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/notetype/RenameCardTemplateDialog.kt @@ -36,6 +36,7 @@ class RenameCardTemplateDialog { } .input( hint = CollectionManager.TR.actionsNewName(), + displayKeyboard = true, allowEmpty = false, prefill = prefill, waitForPositiveButton = true, From c3da9b615f7da1b9019f1911c188dbdc01170989 Mon Sep 17 00:00:00 2001 From: AnkiDroid Translations Date: Mon, 3 Jun 2024 17:47:05 +0000 Subject: [PATCH 042/138] Updated strings from Crowdin --- AnkiDroid/src/main/res/values-af/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-am/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ar/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-az/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-be/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-bg/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-bn/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ca/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ckb/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-cs/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-da/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-de/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-el/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-eo/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-et/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-eu/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-fa/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-fi/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-fil/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-fr/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-fy/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ga/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-gl/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-got/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-gu/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-heb/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-hi/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-hr/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-hu/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-hy/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ind/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-is/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-it/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-iw/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ja/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-jv/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ka/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-kk/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-km/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-kn/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ko/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ku/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ky/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-lt/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-lv/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-mk/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ml/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-mn/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-mr/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ms/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-my/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-nl/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-nn/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-no/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-or/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-pa/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-pl/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ro/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ru/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-sat/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-sc/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-sk/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-sl/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-sq/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-sr/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ss/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-sv/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-sw/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ta/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-te/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-tg/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-tgl/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-th/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ti/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-tn/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-tr/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ts/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-tt/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-uk/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ur/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-uz/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-ve/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-vi/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-wo/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-xh/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-yue/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml | 5 +++++ AnkiDroid/src/main/res/values-zu/03-dialogs.xml | 5 +++++ 93 files changed, 465 insertions(+) diff --git a/AnkiDroid/src/main/res/values-af/03-dialogs.xml b/AnkiDroid/src/main/res/values-af/03-dialogs.xml index cf275cd3e3fe..8bcd85da7f0d 100644 --- a/AnkiDroid/src/main/res/values-af/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-af/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-am/03-dialogs.xml b/AnkiDroid/src/main/res/values-am/03-dialogs.xml index c5e8a9dd7b11..af3c6d8eb6de 100644 --- a/AnkiDroid/src/main/res/values-am/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-am/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ar/03-dialogs.xml b/AnkiDroid/src/main/res/values-ar/03-dialogs.xml index 1a643ee8ebcf..fbb9e47874da 100644 --- a/AnkiDroid/src/main/res/values-ar/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ar/03-dialogs.xml @@ -284,4 +284,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-az/03-dialogs.xml b/AnkiDroid/src/main/res/values-az/03-dialogs.xml index 4a1127147717..1c85e9a659d1 100644 --- a/AnkiDroid/src/main/res/values-az/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-az/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-be/03-dialogs.xml b/AnkiDroid/src/main/res/values-be/03-dialogs.xml index cf81736a1476..078eed638527 100644 --- a/AnkiDroid/src/main/res/values-be/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-be/03-dialogs.xml @@ -270,4 +270,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-bg/03-dialogs.xml b/AnkiDroid/src/main/res/values-bg/03-dialogs.xml index 77d44a385716..30df386727d0 100644 --- a/AnkiDroid/src/main/res/values-bg/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-bg/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-bn/03-dialogs.xml b/AnkiDroid/src/main/res/values-bn/03-dialogs.xml index 9282a75c0802..912a52288bc5 100644 --- a/AnkiDroid/src/main/res/values-bn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-bn/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ca/03-dialogs.xml b/AnkiDroid/src/main/res/values-ca/03-dialogs.xml index 2197fc69860f..64b90ff7397c 100644 --- a/AnkiDroid/src/main/res/values-ca/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ca/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml b/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml index 11576ebb6259..94f9cc8fe29a 100644 --- a/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-cs/03-dialogs.xml b/AnkiDroid/src/main/res/values-cs/03-dialogs.xml index 11603086801a..fe1105ee1aaf 100644 --- a/AnkiDroid/src/main/res/values-cs/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-cs/03-dialogs.xml @@ -268,4 +268,9 @@ Od Do + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-da/03-dialogs.xml b/AnkiDroid/src/main/res/values-da/03-dialogs.xml index a52c42ca3179..9860c38099d6 100644 --- a/AnkiDroid/src/main/res/values-da/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-da/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-de/03-dialogs.xml b/AnkiDroid/src/main/res/values-de/03-dialogs.xml index c0e3a956084a..e3b1073db017 100644 --- a/AnkiDroid/src/main/res/values-de/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-de/03-dialogs.xml @@ -250,4 +250,9 @@ Von Bis + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-el/03-dialogs.xml b/AnkiDroid/src/main/res/values-el/03-dialogs.xml index cff76b3405ee..e9391d422e48 100644 --- a/AnkiDroid/src/main/res/values-el/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-el/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-eo/03-dialogs.xml b/AnkiDroid/src/main/res/values-eo/03-dialogs.xml index 665b59a025be..8435ddf6b04b 100644 --- a/AnkiDroid/src/main/res/values-eo/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-eo/03-dialogs.xml @@ -252,4 +252,9 @@ De post Ĝis + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml b/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml index 59c4c9e79e99..575249c9d4a7 100644 --- a/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml @@ -252,4 +252,9 @@ De A + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml b/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml index 5c0e47acd46a..7cf89c9165fe 100644 --- a/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml @@ -252,4 +252,9 @@ De A + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-et/03-dialogs.xml b/AnkiDroid/src/main/res/values-et/03-dialogs.xml index 49476a9ea389..e6dbe6ff3344 100644 --- a/AnkiDroid/src/main/res/values-et/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-et/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-eu/03-dialogs.xml b/AnkiDroid/src/main/res/values-eu/03-dialogs.xml index af2c1a9ce643..3ec526b29e0c 100644 --- a/AnkiDroid/src/main/res/values-eu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-eu/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-fa/03-dialogs.xml b/AnkiDroid/src/main/res/values-fa/03-dialogs.xml index 9092337cf704..718f1bb46eb4 100644 --- a/AnkiDroid/src/main/res/values-fa/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fa/03-dialogs.xml @@ -250,4 +250,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-fi/03-dialogs.xml b/AnkiDroid/src/main/res/values-fi/03-dialogs.xml index 4e5d681fa26c..fccfb710b9e6 100644 --- a/AnkiDroid/src/main/res/values-fi/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fi/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-fil/03-dialogs.xml b/AnkiDroid/src/main/res/values-fil/03-dialogs.xml index f4da17150725..12a9c8bb3d7e 100644 --- a/AnkiDroid/src/main/res/values-fil/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fil/03-dialogs.xml @@ -253,4 +253,9 @@ Mga file na may di-wastong pag-encode:%d Mula Hanggang + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-fr/03-dialogs.xml b/AnkiDroid/src/main/res/values-fr/03-dialogs.xml index f22c1abc3786..af4f4e955d7d 100644 --- a/AnkiDroid/src/main/res/values-fr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fr/03-dialogs.xml @@ -250,4 +250,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-fy/03-dialogs.xml b/AnkiDroid/src/main/res/values-fy/03-dialogs.xml index 2ad24d3e47c8..3a048687c825 100644 --- a/AnkiDroid/src/main/res/values-fy/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fy/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ga/03-dialogs.xml b/AnkiDroid/src/main/res/values-ga/03-dialogs.xml index f85aeb627686..2df5fad0570b 100644 --- a/AnkiDroid/src/main/res/values-ga/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ga/03-dialogs.xml @@ -276,4 +276,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-gl/03-dialogs.xml b/AnkiDroid/src/main/res/values-gl/03-dialogs.xml index eb9742aec957..8f54d267fe52 100644 --- a/AnkiDroid/src/main/res/values-gl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-gl/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-got/03-dialogs.xml b/AnkiDroid/src/main/res/values-got/03-dialogs.xml index 4d2e1ea27ce7..592c9a81db86 100644 --- a/AnkiDroid/src/main/res/values-got/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-got/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-gu/03-dialogs.xml b/AnkiDroid/src/main/res/values-gu/03-dialogs.xml index cdc0632ad6a6..877ac48e3a1d 100644 --- a/AnkiDroid/src/main/res/values-gu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-gu/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-heb/03-dialogs.xml b/AnkiDroid/src/main/res/values-heb/03-dialogs.xml index 5bf99fb5bcca..ae1de9833d98 100644 --- a/AnkiDroid/src/main/res/values-heb/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-heb/03-dialogs.xml @@ -267,4 +267,9 @@ - מ אל + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-hi/03-dialogs.xml b/AnkiDroid/src/main/res/values-hi/03-dialogs.xml index 87babbe85e4f..3b10cf439538 100644 --- a/AnkiDroid/src/main/res/values-hi/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hi/03-dialogs.xml @@ -252,4 +252,9 @@ से को + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-hr/03-dialogs.xml b/AnkiDroid/src/main/res/values-hr/03-dialogs.xml index 1bbbd1692c9f..18687893667f 100644 --- a/AnkiDroid/src/main/res/values-hr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hr/03-dialogs.xml @@ -260,4 +260,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-hu/03-dialogs.xml b/AnkiDroid/src/main/res/values-hu/03-dialogs.xml index 479d45d48ffe..f285107c995b 100644 --- a/AnkiDroid/src/main/res/values-hu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hu/03-dialogs.xml @@ -250,4 +250,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-hy/03-dialogs.xml b/AnkiDroid/src/main/res/values-hy/03-dialogs.xml index 43a2b5fcdea6..7da68d6c3212 100644 --- a/AnkiDroid/src/main/res/values-hy/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hy/03-dialogs.xml @@ -250,4 +250,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ind/03-dialogs.xml b/AnkiDroid/src/main/res/values-ind/03-dialogs.xml index fb8083327649..1123d27f4c85 100644 --- a/AnkiDroid/src/main/res/values-ind/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ind/03-dialogs.xml @@ -244,4 +244,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-is/03-dialogs.xml b/AnkiDroid/src/main/res/values-is/03-dialogs.xml index e0e13832835f..97b251aaeb27 100644 --- a/AnkiDroid/src/main/res/values-is/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-is/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-it/03-dialogs.xml b/AnkiDroid/src/main/res/values-it/03-dialogs.xml index 90f514588664..2ff9894b130b 100644 --- a/AnkiDroid/src/main/res/values-it/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-it/03-dialogs.xml @@ -252,4 +252,9 @@ Da A + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-iw/03-dialogs.xml b/AnkiDroid/src/main/res/values-iw/03-dialogs.xml index 5bf99fb5bcca..ae1de9833d98 100644 --- a/AnkiDroid/src/main/res/values-iw/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-iw/03-dialogs.xml @@ -267,4 +267,9 @@ - מ אל + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml index fdd426f30128..890b90d7ea84 100644 --- a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml @@ -243,4 +243,9 @@ 最短 最長 + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-jv/03-dialogs.xml b/AnkiDroid/src/main/res/values-jv/03-dialogs.xml index 0192e5de0c15..06de335bdd1f 100644 --- a/AnkiDroid/src/main/res/values-jv/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-jv/03-dialogs.xml @@ -244,4 +244,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ka/03-dialogs.xml b/AnkiDroid/src/main/res/values-ka/03-dialogs.xml index 072d968141ec..4ad5b628e6ae 100644 --- a/AnkiDroid/src/main/res/values-ka/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ka/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-kk/03-dialogs.xml b/AnkiDroid/src/main/res/values-kk/03-dialogs.xml index c8bba6ee9b3b..d47e4a1cccc6 100644 --- a/AnkiDroid/src/main/res/values-kk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-kk/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-km/03-dialogs.xml b/AnkiDroid/src/main/res/values-km/03-dialogs.xml index b755b9b75c94..5a60f84d19a5 100644 --- a/AnkiDroid/src/main/res/values-km/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-km/03-dialogs.xml @@ -244,4 +244,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-kn/03-dialogs.xml b/AnkiDroid/src/main/res/values-kn/03-dialogs.xml index 1d81ed09576b..89bf9c84564d 100644 --- a/AnkiDroid/src/main/res/values-kn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-kn/03-dialogs.xml @@ -250,4 +250,9 @@ ನಿಂದ ಗೆ + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ko/03-dialogs.xml b/AnkiDroid/src/main/res/values-ko/03-dialogs.xml index ccc65f642b61..e2df16252f13 100644 --- a/AnkiDroid/src/main/res/values-ko/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ko/03-dialogs.xml @@ -244,4 +244,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ku/03-dialogs.xml b/AnkiDroid/src/main/res/values-ku/03-dialogs.xml index 11576ebb6259..94f9cc8fe29a 100644 --- a/AnkiDroid/src/main/res/values-ku/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ku/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ky/03-dialogs.xml b/AnkiDroid/src/main/res/values-ky/03-dialogs.xml index 5e909b14f5bc..5f2ddce32012 100644 --- a/AnkiDroid/src/main/res/values-ky/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ky/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-lt/03-dialogs.xml b/AnkiDroid/src/main/res/values-lt/03-dialogs.xml index 6edd83c05bba..59b0a365e4a6 100644 --- a/AnkiDroid/src/main/res/values-lt/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-lt/03-dialogs.xml @@ -268,4 +268,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-lv/03-dialogs.xml b/AnkiDroid/src/main/res/values-lv/03-dialogs.xml index 6adcd381dc72..a1f57db242f1 100644 --- a/AnkiDroid/src/main/res/values-lv/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-lv/03-dialogs.xml @@ -260,4 +260,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-mk/03-dialogs.xml b/AnkiDroid/src/main/res/values-mk/03-dialogs.xml index e547dd7ff316..427b8219533a 100644 --- a/AnkiDroid/src/main/res/values-mk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mk/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ml/03-dialogs.xml b/AnkiDroid/src/main/res/values-ml/03-dialogs.xml index 7e8ae5fc25db..3ff88567f68a 100644 --- a/AnkiDroid/src/main/res/values-ml/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ml/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-mn/03-dialogs.xml b/AnkiDroid/src/main/res/values-mn/03-dialogs.xml index 58460e4c2800..ba813c1ca091 100644 --- a/AnkiDroid/src/main/res/values-mn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mn/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-mr/03-dialogs.xml b/AnkiDroid/src/main/res/values-mr/03-dialogs.xml index f336fe98b0eb..224b229e5c33 100644 --- a/AnkiDroid/src/main/res/values-mr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mr/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ms/03-dialogs.xml b/AnkiDroid/src/main/res/values-ms/03-dialogs.xml index 72a1d5a5122d..cb3cbe77c319 100644 --- a/AnkiDroid/src/main/res/values-ms/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ms/03-dialogs.xml @@ -244,4 +244,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-my/03-dialogs.xml b/AnkiDroid/src/main/res/values-my/03-dialogs.xml index f29d16570771..d5ea8af44489 100644 --- a/AnkiDroid/src/main/res/values-my/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-my/03-dialogs.xml @@ -244,4 +244,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-nl/03-dialogs.xml b/AnkiDroid/src/main/res/values-nl/03-dialogs.xml index eef320616ebe..0ac39909f39e 100644 --- a/AnkiDroid/src/main/res/values-nl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-nl/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-nn/03-dialogs.xml b/AnkiDroid/src/main/res/values-nn/03-dialogs.xml index 5aff046b25f5..c0bdf172618a 100644 --- a/AnkiDroid/src/main/res/values-nn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-nn/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-no/03-dialogs.xml b/AnkiDroid/src/main/res/values-no/03-dialogs.xml index c160dc5426e5..8b8d39cc8d67 100644 --- a/AnkiDroid/src/main/res/values-no/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-no/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-or/03-dialogs.xml b/AnkiDroid/src/main/res/values-or/03-dialogs.xml index 0d8fc98b3cd8..d3700f87ef7c 100644 --- a/AnkiDroid/src/main/res/values-or/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-or/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-pa/03-dialogs.xml b/AnkiDroid/src/main/res/values-pa/03-dialogs.xml index f3c548c87017..6f53ac8f3795 100644 --- a/AnkiDroid/src/main/res/values-pa/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pa/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-pl/03-dialogs.xml b/AnkiDroid/src/main/res/values-pl/03-dialogs.xml index 27f9a382af1c..94ab64ad2362 100644 --- a/AnkiDroid/src/main/res/values-pl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pl/03-dialogs.xml @@ -268,4 +268,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml b/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml index ecd64c7e1446..b95b0f7a8dea 100644 --- a/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml @@ -252,4 +252,9 @@ De Para + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml b/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml index 8e6bc85d36d6..0b5368e28cb7 100644 --- a/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml @@ -252,4 +252,9 @@ - Desde Até + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ro/03-dialogs.xml b/AnkiDroid/src/main/res/values-ro/03-dialogs.xml index 3719a82ef857..8519fbbf55fa 100644 --- a/AnkiDroid/src/main/res/values-ro/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ro/03-dialogs.xml @@ -260,4 +260,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ru/03-dialogs.xml b/AnkiDroid/src/main/res/values-ru/03-dialogs.xml index 7d216cf30ee6..ec47b38fa09c 100644 --- a/AnkiDroid/src/main/res/values-ru/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ru/03-dialogs.xml @@ -269,4 +269,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-sat/03-dialogs.xml b/AnkiDroid/src/main/res/values-sat/03-dialogs.xml index 91d51e9be437..21da876ac53e 100644 --- a/AnkiDroid/src/main/res/values-sat/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sat/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-sc/03-dialogs.xml b/AnkiDroid/src/main/res/values-sc/03-dialogs.xml index 34075bb49156..534428be80d4 100644 --- a/AnkiDroid/src/main/res/values-sc/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sc/03-dialogs.xml @@ -266,4 +266,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-sk/03-dialogs.xml b/AnkiDroid/src/main/res/values-sk/03-dialogs.xml index 9d017e433991..d95f0fb89431 100644 --- a/AnkiDroid/src/main/res/values-sk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sk/03-dialogs.xml @@ -266,4 +266,9 @@ od do + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-sl/03-dialogs.xml b/AnkiDroid/src/main/res/values-sl/03-dialogs.xml index f0e7b2ec2740..8babbe59a27e 100644 --- a/AnkiDroid/src/main/res/values-sl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sl/03-dialogs.xml @@ -268,4 +268,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-sq/03-dialogs.xml b/AnkiDroid/src/main/res/values-sq/03-dialogs.xml index 7a870e61be7a..50399f3f5600 100644 --- a/AnkiDroid/src/main/res/values-sq/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sq/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-sr/03-dialogs.xml b/AnkiDroid/src/main/res/values-sr/03-dialogs.xml index 354e33d1fbf8..dfb9038009cd 100644 --- a/AnkiDroid/src/main/res/values-sr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sr/03-dialogs.xml @@ -260,4 +260,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ss/03-dialogs.xml b/AnkiDroid/src/main/res/values-ss/03-dialogs.xml index 58460e4c2800..ba813c1ca091 100644 --- a/AnkiDroid/src/main/res/values-ss/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ss/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-sv/03-dialogs.xml b/AnkiDroid/src/main/res/values-sv/03-dialogs.xml index 35ba83908c1b..c6e71752e0c5 100644 --- a/AnkiDroid/src/main/res/values-sv/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sv/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-sw/03-dialogs.xml b/AnkiDroid/src/main/res/values-sw/03-dialogs.xml index 58460e4c2800..ba813c1ca091 100644 --- a/AnkiDroid/src/main/res/values-sw/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sw/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ta/03-dialogs.xml b/AnkiDroid/src/main/res/values-ta/03-dialogs.xml index abc5b1874af0..d27ab99ca902 100644 --- a/AnkiDroid/src/main/res/values-ta/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ta/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-te/03-dialogs.xml b/AnkiDroid/src/main/res/values-te/03-dialogs.xml index 2285c55a28fd..e70b2dd7b156 100644 --- a/AnkiDroid/src/main/res/values-te/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-te/03-dialogs.xml @@ -252,4 +252,9 @@ నుండి కు + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-tg/03-dialogs.xml b/AnkiDroid/src/main/res/values-tg/03-dialogs.xml index 70903050bfcc..06b2b84615e7 100644 --- a/AnkiDroid/src/main/res/values-tg/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tg/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml b/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml index 4dbd8c273b6c..1d4831513b6a 100644 --- a/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-th/03-dialogs.xml b/AnkiDroid/src/main/res/values-th/03-dialogs.xml index 0192e5de0c15..06de335bdd1f 100644 --- a/AnkiDroid/src/main/res/values-th/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-th/03-dialogs.xml @@ -244,4 +244,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ti/03-dialogs.xml b/AnkiDroid/src/main/res/values-ti/03-dialogs.xml index 58460e4c2800..ba813c1ca091 100644 --- a/AnkiDroid/src/main/res/values-ti/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ti/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-tn/03-dialogs.xml b/AnkiDroid/src/main/res/values-tn/03-dialogs.xml index 58460e4c2800..ba813c1ca091 100644 --- a/AnkiDroid/src/main/res/values-tn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tn/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-tr/03-dialogs.xml b/AnkiDroid/src/main/res/values-tr/03-dialogs.xml index f22fae3bd310..003035d01884 100644 --- a/AnkiDroid/src/main/res/values-tr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tr/03-dialogs.xml @@ -252,4 +252,9 @@ En erken En geç + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ts/03-dialogs.xml b/AnkiDroid/src/main/res/values-ts/03-dialogs.xml index 58460e4c2800..ba813c1ca091 100644 --- a/AnkiDroid/src/main/res/values-ts/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ts/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-tt/03-dialogs.xml b/AnkiDroid/src/main/res/values-tt/03-dialogs.xml index 0752aeeced57..9d92aa02a9e0 100644 --- a/AnkiDroid/src/main/res/values-tt/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tt/03-dialogs.xml @@ -244,4 +244,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-uk/03-dialogs.xml b/AnkiDroid/src/main/res/values-uk/03-dialogs.xml index 328849cc188f..776d01233504 100644 --- a/AnkiDroid/src/main/res/values-uk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-uk/03-dialogs.xml @@ -268,4 +268,9 @@ Від До + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ur/03-dialogs.xml b/AnkiDroid/src/main/res/values-ur/03-dialogs.xml index 261d4bab6ea2..9742d98e92f6 100644 --- a/AnkiDroid/src/main/res/values-ur/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ur/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-uz/03-dialogs.xml b/AnkiDroid/src/main/res/values-uz/03-dialogs.xml index 1574387be9bd..6367030dc171 100644 --- a/AnkiDroid/src/main/res/values-uz/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-uz/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-ve/03-dialogs.xml b/AnkiDroid/src/main/res/values-ve/03-dialogs.xml index 58460e4c2800..ba813c1ca091 100644 --- a/AnkiDroid/src/main/res/values-ve/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ve/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-vi/03-dialogs.xml b/AnkiDroid/src/main/res/values-vi/03-dialogs.xml index cdfbfeac9b2e..44771d263b80 100644 --- a/AnkiDroid/src/main/res/values-vi/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-vi/03-dialogs.xml @@ -244,4 +244,9 @@ Từ Đến + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-wo/03-dialogs.xml b/AnkiDroid/src/main/res/values-wo/03-dialogs.xml index 0192e5de0c15..06de335bdd1f 100644 --- a/AnkiDroid/src/main/res/values-wo/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-wo/03-dialogs.xml @@ -244,4 +244,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-xh/03-dialogs.xml b/AnkiDroid/src/main/res/values-xh/03-dialogs.xml index 58460e4c2800..ba813c1ca091 100644 --- a/AnkiDroid/src/main/res/values-xh/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-xh/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-yue/03-dialogs.xml b/AnkiDroid/src/main/res/values-yue/03-dialogs.xml index 5af1f56ac648..1f4c4a5471eb 100644 --- a/AnkiDroid/src/main/res/values-yue/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-yue/03-dialogs.xml @@ -244,4 +244,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml index b8c6ecc0fc9a..3b73d140f96a 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml @@ -244,4 +244,9 @@ + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml b/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml index 65e9ba8d1fe7..c7c17dcd2cb3 100644 --- a/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml @@ -244,4 +244,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-zu/03-dialogs.xml b/AnkiDroid/src/main/res/values-zu/03-dialogs.xml index 58460e4c2800..ba813c1ca091 100644 --- a/AnkiDroid/src/main/res/values-zu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zu/03-dialogs.xml @@ -252,4 +252,9 @@ From To + + Cloze Type Note Required + No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. + Open + Single tap text to cloze From 7030339ed83ba0089b5d29c4e2f290094cbafc18 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Sun, 2 Jun 2024 17:17:25 -0500 Subject: [PATCH 043/138] test(reviewer): accept different view names for custom scheduler tests without this, `./gradlew jacocoAndroidTestReport` would not work on the command line, but the tests would work in Android Studio, which is quite bizarre --- .../java/com/ichi2/anki/ReviewerTest.kt | 60 ++++++++++++++----- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerTest.kt index e3903c3fb6bf..3ce9d3d3c528 100755 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerTest.kt @@ -17,17 +17,20 @@ package com.ichi2.anki import androidx.recyclerview.widget.RecyclerView import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.NoMatchingViewException import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.contrib.RecyclerViewActions import androidx.test.espresso.matcher.ViewMatchers.hasDescendant import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withResourceName import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import com.ichi2.anki.tests.InstrumentedTest import com.ichi2.anki.testutil.GrantStoragePermission.storagePermission +import com.ichi2.anki.testutil.ThreadUtils import com.ichi2.anki.testutil.grantPermissions import com.ichi2.anki.testutil.notificationPermission import com.ichi2.libanki.Collection @@ -38,7 +41,7 @@ import org.hamcrest.Matchers.equalTo import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import java.util.concurrent.TimeUnit +import java.lang.AssertionError @RunWith(AndroidJUnit4::class) class ReviewerTest : InstrumentedTest() { @@ -87,10 +90,21 @@ class ReviewerTest : InstrumentedTest() { clickShowAnswerAndAnswerGood() - cardFromDb = col.getCard(card.id).toBackendCard() - assertThat(cardFromDb.easeFactor, equalTo(3000)) - assertThat(cardFromDb.interval, equalTo(123)) - assertThat(cardFromDb.customData, equalTo("""{"c":2}""")) + fun runAssertion() { + cardFromDb = col.getCard(card.id).toBackendCard() + assertThat(cardFromDb.easeFactor, equalTo(3000)) + assertThat(cardFromDb.interval, equalTo(123)) + assertThat(cardFromDb.customData, equalTo("""{"c":2}""")) + } + + try { + runAssertion() + } catch (e: Exception) { + // Give separate threads a greater chance of doing the custom scheduling + // if the card scheduling values aren't updated immediately + ThreadUtils.sleep(2000) + runAssertion() + } } @Test @@ -139,11 +153,23 @@ class ReviewerTest : InstrumentedTest() { private fun clickShowAnswerAndAnswerGood() { clickShowAnswer() ensureAnswerButtonsAreDisplayed() - onView(withId(R.id.flashcard_layout_ease3)).perform(click()) + try { + // ...on the command line it has resource name "good_button"... + onView(withResourceName("good_button")).perform(click()) + } catch (e: NoMatchingViewException) { + // ...but in Android Studio it has resource name "flashcard_layout_ease3" !? + onView(withResourceName("flashcard_layout_ease3")).perform(click()) + } } private fun clickShowAnswer() { - onView(withId(R.id.flashcard_layout_flip)).perform(click()) + try { + // ... on the command line, it has resource name "show_answer"... + onView(withResourceName("show_answer")).perform(click()) + } catch (e: NoMatchingViewException) { + // ... but in Android Studio it has resource name "flashcard_layout_flip" !? + onView(withResourceName("flashcard_layout_flip")).perform(click()) + } } private fun ensureAnswerButtonsAreDisplayed() { @@ -151,13 +177,19 @@ class ReviewerTest : InstrumentedTest() { // the messages to be passed in and out of the WebView when evaluating // the custom JS scheduler code. The ease buttons are hidden until the // custom scheduler has finished running - onView(withId(R.id.flashcard_layout_ease3)).checkWithTimeout( - matches(isDisplayed()), - 100, - // Increase to a max of 30 seconds because CI builds can be very - // slow - TimeUnit.SECONDS.toMillis(30) - ) + try { + // ...on the command line it has resource name "good_button"... + onView(withResourceName("good_button")).checkWithTimeout( + matches(isDisplayed()), + 100 + ) + } catch (e: AssertionError) { + // ...but in Android Studio it has resource name "flashcard_layout_ease3" !? + onView(withResourceName("flashcard_layout_ease3")).checkWithTimeout( + matches(isDisplayed()), + 100 + ) + } } } From 8d5d3dac9373f7616a8a1398dd76d01b2cbc898c Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Sun, 2 Jun 2024 17:23:53 -0500 Subject: [PATCH 044/138] test(custom-scheduler): add retries, re-enable in CI with appropriate retries it appears to work reliably --- .../java/com/ichi2/anki/ReviewerFragmentTest.kt | 8 ++++---- .../src/androidTest/java/com/ichi2/anki/ReviewerTest.kt | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerFragmentTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerFragmentTest.kt index 34f653feeaa1..cb090c1e6367 100644 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerFragmentTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerFragmentTest.kt @@ -27,12 +27,11 @@ import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import com.ichi2.anki.preferences.sharedPrefs import com.ichi2.anki.tests.InstrumentedTest +import com.ichi2.anki.tests.libanki.RetryRule import com.ichi2.anki.testutil.GrantStoragePermission.storagePermission import com.ichi2.anki.testutil.grantPermissions import com.ichi2.anki.testutil.notificationPermission import com.ichi2.libanki.Collection -import com.ichi2.testutils.Flaky -import com.ichi2.testutils.OS import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.equalTo import org.junit.Rule @@ -56,8 +55,10 @@ class ReviewerFragmentTest : InstrumentedTest() { @get:Rule val runtimePermissionRule = grantPermissions(storagePermission, notificationPermission) + @get:Rule + val retry = RetryRule(10) + @Test - @Flaky(os = OS.ALL, "Fails on CI with timing issues frequently") fun testCustomSchedulerWithCustomData() { setNewReviewer() col.cardStateCustomizer = @@ -95,7 +96,6 @@ class ReviewerFragmentTest : InstrumentedTest() { } @Test - @Flaky(os = OS.ALL, "Fails on CI with timing issues frequently") fun testCustomSchedulerWithRuntimeError() { setNewReviewer() // Issue 15035 - runtime errors weren't handled diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerTest.kt index 3ce9d3d3c528..185a64bddd59 100755 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerTest.kt @@ -29,13 +29,12 @@ import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import com.ichi2.anki.tests.InstrumentedTest +import com.ichi2.anki.tests.libanki.RetryRule import com.ichi2.anki.testutil.GrantStoragePermission.storagePermission import com.ichi2.anki.testutil.ThreadUtils import com.ichi2.anki.testutil.grantPermissions import com.ichi2.anki.testutil.notificationPermission import com.ichi2.libanki.Collection -import com.ichi2.testutils.Flaky -import com.ichi2.testutils.OS import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.equalTo import org.junit.Rule @@ -59,8 +58,10 @@ class ReviewerTest : InstrumentedTest() { @get:Rule val runtimePermissionRule = grantPermissions(storagePermission, notificationPermission) + @get:Rule + val retry = RetryRule(10) + @Test - @Flaky(os = OS.ALL, "Fails on CI with timing issues frequently") fun testCustomSchedulerWithCustomData() { col.cardStateCustomizer = """ @@ -108,7 +109,6 @@ class ReviewerTest : InstrumentedTest() { } @Test - @Flaky(os = OS.ALL, "Fails on CI with timing issues frequently") fun testCustomSchedulerWithRuntimeError() { // Issue 15035 - runtime errors weren't handled col.cardStateCustomizer = "states.this_is_not_defined.normal.review = 12;" From b5acdca0abee6169b898fa688bf2327d38a11be5 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Mon, 3 Jun 2024 19:52:56 +0100 Subject: [PATCH 045/138] fix(note-editor): filtered card sent home after edit If a card in a filtered deck was edited, it was returned home Cause: b455b7b135a8eb003efd862412013ccdbf8196c4 Fixes 16522 --- .../main/java/com/ichi2/anki/NoteEditor.kt | 3 ++- .../java/com/ichi2/anki/NoteEditorTest.kt | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt b/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt index 274fbfb2df5f..9e42f0ac0e39 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt @@ -1070,7 +1070,7 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags // Regular changes in note content var modified = false // changed did? this has to be done first as remFromDyn() involves a direct write to the database - if (currentEditedCard != null && currentEditedCard!!.did != deckId) { + if (currentEditedCard != null && currentEditedCard!!.currentDeckId().did != deckId) { reloadRequired = true undoableOp { setDeck(listOf(currentEditedCard!!.id), deckId) } // refresh the card object to reflect the database changes from above @@ -1080,6 +1080,7 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags // then set the card ID to the new deck currentEditedCard!!.did = deckId modified = true + Timber.d("deck ID updated to '%d'", deckId) } // now load any changes to the fields from the form for (f in editFields!!) { diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/NoteEditorTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/NoteEditorTest.kt index d6d4ba4369e2..6feefd248061 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/NoteEditorTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/NoteEditorTest.kt @@ -426,6 +426,26 @@ class NoteEditorTest : RobolectricTest() { } } + @Test + fun `editing card in filtered deck retains deck`() = runTest { + val homeDeckId = addDeck("A") + val note = addNoteUsingBasicModel().updateCards { did = homeDeckId } + moveToDynamicDeck(note) + + // ensure note is correctly setup + assertThat("home deck", note.firstCard().oDid, equalTo(homeDeckId)) + assertThat("current deck", note.firstCard().did, not(equalTo(homeDeckId))) + + getNoteEditorEditingExistingBasicNote(note, REVIEWER, NoteEditor::class.java).apply { + setField(0, "Hello") + saveNote() + } + + // ensure note is correctly setup + assertThat("after: home deck", note.firstCard().oDid, equalTo(homeDeckId)) + assertThat("after: current deck", note.firstCard().did, not(equalTo(homeDeckId))) + } + private fun moveToDynamicDeck(note: Note): DeckId { val dyn = addDynamicDeck("All") col.decks.select(dyn) From 812fd2cbc286768450a9bdd28dabe1eb5223bec1 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Tue, 4 Jun 2024 13:53:44 +0100 Subject: [PATCH 046/138] chore(card-browser): logs Diagnostics for https://redirect.github.com/ankidroid/Anki-Android/issues/16541 --- .../java/com/ichi2/anki/browser/CardBrowserViewModel.kt | 3 +++ .../src/main/java/com/ichi2/libanki/sched/Scheduler.kt | 8 ++++++-- AnkiDroid/src/test/java/com/ichi2/testutils/JvmTest.kt | 2 +- .../test/java/com/ichi2/testutils/TestChangeSubscriber.kt | 1 + 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index 2216f1a92962..c9e08b424370 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -386,12 +386,14 @@ class CardBrowserViewModel( fun selectAll() { if (_selectedRows.addAll(cards.wrapped)) { + Timber.d("selecting all: %d item(s)", cards.wrapped.size) refreshSelectedRowsFlow() } } fun selectNone() { if (_selectedRows.isEmpty()) return + Timber.d("selecting none") _selectedRows.clear() refreshSelectedRowsFlow() } @@ -482,6 +484,7 @@ class CardBrowserViewModel( sched.suspendCards(cardIds).changes } } + Timber.d("finished 'toggleSuspendCards'") } /** diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/sched/Scheduler.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/sched/Scheduler.kt index 745d003f7b91..dba03fb068ba 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/sched/Scheduler.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/sched/Scheduler.kt @@ -232,8 +232,10 @@ open class Scheduler(val col: Collection) { * @param ids Id of cards to suspend */ open fun suspendCards(ids: Iterable): OpChangesWithCount { + val cids = ids.toList() + Timber.i("suspending %d card(s)", cids.size) return col.backend.buryOrSuspendCards( - cardIds = ids.toList(), + cardIds = cids, noteIds = listOf(), mode = BuryOrSuspendCardsRequest.Mode.SUSPEND ) @@ -251,8 +253,10 @@ open class Scheduler(val col: Collection) { * @param ids Id of cards to unsuspend */ open fun unsuspendCards(ids: Iterable): OpChanges { + val cids = ids.toList() + Timber.i("unsuspending %d card(s)", cids.size) return col.backend.restoreBuriedAndSuspendedCards( - cids = ids.toList() + cids = cids ) } diff --git a/AnkiDroid/src/test/java/com/ichi2/testutils/JvmTest.kt b/AnkiDroid/src/test/java/com/ichi2/testutils/JvmTest.kt index 43718d637d27..fad6d9de71ce 100644 --- a/AnkiDroid/src/test/java/com/ichi2/testutils/JvmTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/testutils/JvmTest.kt @@ -104,7 +104,7 @@ open class JvmTest : TestClass { Dispatchers.resetMain() runBlocking { CollectionManager.discardBackend() } Timber.uprootAll() - println("""-- executing test "${testName.methodName}"""") + println("""-- completed test "${testName.methodName}"""") } fun assumeThat(actual: T, matcher: Matcher?) { diff --git a/AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt b/AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt index c48d2309d075..e698a7462092 100644 --- a/AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt +++ b/AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt @@ -45,6 +45,7 @@ suspend fun ensureOpsExecuted(count: Int, block: suspend () -> Unit) { Timber.d("ChangeManager op detected") changes++ } + Timber.v("Listening for ChangeManager ops") block() // we should be fine to not cleanup here, as the subscriber goes out of scope assertThat("ChangeManager: expected $count calls", changes, equalTo(count)) From f2cca9332b862d4b642ab5566984f37fedb8f582 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Tue, 4 Jun 2024 12:53:26 +0100 Subject: [PATCH 047/138] test: improve 'getLatestAlertDialog' error Previously this resulted in a `NullPointerException` before: ``` java.lang.NullPointerException: null cannot be cast to non-null type androidx.appcompat.app.AlertDialog ``` after: ``` org.opentest4j.AssertionFailedError: A dialog should be displayed ==> expected: not ``` Seen in https://redirect.github.com/ankidroid/Anki-Android/pull/16529 --- AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt index 17a6d2e052d8..42f65cce7587 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt @@ -65,6 +65,7 @@ import org.robolectric.shadows.ShadowLog import org.robolectric.shadows.ShadowLooper import org.robolectric.shadows.ShadowMediaPlayer import timber.log.Timber +import kotlin.test.assertNotNull open class RobolectricTest : AndroidTest { @@ -197,7 +198,7 @@ open class RobolectricTest : AndroidTest { * Click on a dialog button for an AlertDialog dialog box. Replaces the above helper. */ protected fun clickAlertDialogButton(button: Int, @Suppress("SameParameterValue") checkDismissed: Boolean) { - val dialog = ShadowDialog.getLatestDialog() as AlertDialog + val dialog = getLatestAlertDialog() dialog.getButton(button).performClick() // Need to run UI thread tasks to actually run the onClickHandler @@ -216,7 +217,7 @@ open class RobolectricTest : AndroidTest { * TODO: Rename to getDialogText when all MaterialDialogs are changed to AlertDialogs */ protected fun getAlertDialogText(@Suppress("SameParameterValue") checkDismissed: Boolean): String? { - val dialog = ShadowDialog.getLatestDialog() as AlertDialog + val dialog = getLatestAlertDialog() if (checkDismissed && Shadows.shadowOf(dialog).hasBeenDismissed()) { Timber.e("The latest dialog has already been dismissed.") return null @@ -480,3 +481,6 @@ open class RobolectricTest : AndroidTest { } } } + +private fun getLatestAlertDialog(): AlertDialog = + assertNotNull(ShadowDialog.getLatestDialog() as? AlertDialog, "A dialog should be displayed") From aec1987ceb00d8aef8c58a77be572039ed728ff7 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Tue, 4 Jun 2024 19:46:43 +0100 Subject: [PATCH 048/138] tests(card-browser-view-model): export data --- .../anki/browser/CardBrowserViewModel.kt | 2 +- .../anki/browser/CardBrowserViewModelTest.kt | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index c9e08b424370..fc51d47457cf 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -529,7 +529,7 @@ class CardBrowserViewModel( } suspend fun getSelectionExportData(): Pair>? { - if (!isInMultiSelectMode) return null + if (!hasSelectedAnyRows()) return null return when (cardsOrNotes) { CARDS -> Pair(ExportDialogFragment.ExportType.Cards, selectedRowIds) NOTES -> Pair( diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index 1d010a9ccecc..5390db0a1125 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -27,6 +27,7 @@ import com.ichi2.anki.Flag import com.ichi2.anki.NoteEditor import com.ichi2.anki.browser.CardBrowserLaunchOptions.DeepLink import com.ichi2.anki.browser.CardBrowserLaunchOptions.SystemContextMenu +import com.ichi2.anki.export.ExportDialogFragment import com.ichi2.anki.flagCardForNote import com.ichi2.anki.model.CardsOrNotes import com.ichi2.anki.model.SortType.EASE @@ -49,6 +50,7 @@ import kotlinx.coroutines.flow.first import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.containsInAnyOrder import org.hamcrest.Matchers.equalTo +import org.hamcrest.Matchers.hasSize import org.hamcrest.Matchers.lessThan import org.hamcrest.Matchers.not import org.hamcrest.Matchers.nullValue @@ -59,6 +61,7 @@ import java.io.File import kotlin.io.path.createTempDirectory import kotlin.io.path.pathString import kotlin.test.assertNotNull +import kotlin.test.assertNull @RunWith(AndroidJUnit4::class) class CardBrowserViewModelTest : JvmTest() { @@ -464,6 +467,35 @@ class CardBrowserViewModelTest : JvmTest() { } } + @Test + fun `export - no selection`() = runViewModelTest(notes = 2) { + assertNull(getSelectionExportData(), "no export data if no selection") + } + + @Test + fun `export - one card`() = runViewModelTest(notes = 2) { + selectRowsWithPositions(0) + + val (exportType, ids) = assertNotNull(getSelectionExportData()) + + assertThat(exportType, equalTo(ExportDialogFragment.ExportType.Cards)) + assertThat(ids, hasSize(1)) + + assertThat(ids.single(), equalTo(cards[0].id)) + } + + @Test + fun `export - one note`() = runViewModelNotesTest(notes = 2) { + selectRowsWithPositions(0) + + val (exportType, ids) = assertNotNull(getSelectionExportData()) + + assertThat(exportType, equalTo(ExportDialogFragment.ExportType.Notes)) + assertThat(ids, hasSize(1)) + + assertThat(ids.single(), equalTo(cards[0].card.nid)) + } + private fun runViewModelNotesTest( notes: Int = 0, manualInit: Boolean = true, From b3e96fce8845973d52f122220ccb70c545d8aa2b Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Tue, 4 Jun 2024 21:05:37 +0100 Subject: [PATCH 049/138] chore(card-browser): logs * moved setup higher in setUp to capture more Diagnostics for https://redirect.github.com/ankidroid/Anki-Android/issues/16541 --- .../com/ichi2/anki/browser/CardBrowserViewModel.kt | 2 ++ .../src/main/java/com/ichi2/libanki/ChangeManager.kt | 6 ++++++ .../src/test/java/com/ichi2/anki/RobolectricTest.kt | 12 ++++++------ .../ichi2/anki/browser/CardBrowserViewModelTest.kt | 2 ++ .../src/test/java/com/ichi2/testutils/JvmTest.kt | 8 ++++---- .../java/com/ichi2/testutils/TestChangeSubscriber.kt | 11 +++++++---- 6 files changed, 27 insertions(+), 14 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index fc51d47457cf..5b52bd2f55bc 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -328,6 +328,7 @@ class CardBrowserViewModel( fun manualInit() { require(manualInit) { "'manualInit' should be true" } flowOfInitCompleted.update { true } + Timber.d("manualInit") } /** Whether any rows are selected */ @@ -474,6 +475,7 @@ class CardBrowserViewModel( if (!hasSelectedAnyRows()) { return@launch } + Timber.d("toggling selected cards suspend status") val cardIds = queryAllSelectedCardIds() undoableOp { diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/ChangeManager.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/ChangeManager.kt index 7fd1b1dc3e49..9b2dc455e05d 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/ChangeManager.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/ChangeManager.kt @@ -36,8 +36,10 @@ import anki.collection.OpChangesWithId import anki.import_export.ImportResponse import com.ichi2.anki.CollectionManager.withCol import com.ichi2.anki.CrashReportService +import com.ichi2.anki.utils.ext.ifNotZero import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import timber.log.Timber import java.lang.ref.WeakReference import java.util.concurrent.CopyOnWriteArrayList @@ -54,6 +56,8 @@ object ChangeManager { // Maybe fixes #16217 - CopyOnWriteArrayList makes this object thread-safe private val subscribers = CopyOnWriteArrayList(mutableListOf>()) + val subscriberCount get() = subscribers.size + fun subscribe(subscriber: Subscriber) { subscribers.add(WeakReference(subscriber)) } @@ -73,6 +77,7 @@ object ChangeManager { ref.opExecuted(changes, handler) } } + expired.size.ifNotZero { size -> Timber.v("removing %d expired subscribers", size) } for (item in expired) { subscribers.remove(item) } @@ -80,6 +85,7 @@ object ChangeManager { @VisibleForTesting fun clearSubscribers() { + Timber.d("clearing %d subscribers", subscribers.size) subscribers.clear() } diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt index 42f65cce7587..d4dcb1c23b08 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt @@ -105,6 +105,12 @@ open class RobolectricTest : AndroidTest { TimeManager.resetWith(MockTime(2020, 7, 7, 7, 0, 0, 0, 10)) throwOnShowError = true + // See the Android logging (from Timber) + ShadowLog.stream = System.out + // Filters for non-Timber sources. Prefer filtering in RobolectricDebugTree if possible + // LifecycleMonitor: not needed as we already use registerActivityLifecycleCallbacks for logs + .filter("^(?!(W/ShadowLegacyPath|D/LifecycleMonitor)).*$") // W/ShadowLegacyPath: android.graphics.Path#op() not supported yet. + ChangeManager.clearSubscribers() validateRunWithAnnotationPresent() @@ -120,12 +126,6 @@ open class RobolectricTest : AndroidTest { maybeSetupBackend() - // See the Android logging (from Timber) - ShadowLog.stream = System.out - // Filters for non-Timber sources. Prefer filtering in RobolectricDebugTree if possible - // LifecycleMonitor: not needed as we already use registerActivityLifecycleCallbacks for logs - .filter("^(?!(W/ShadowLegacyPath|D/LifecycleMonitor)).*$") // W/ShadowLegacyPath: android.graphics.Path#op() not supported yet. - Storage.setUseInMemory(useInMemoryDatabase()) // Reset static variable for custom tabs failure. diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index 5390db0a1125..2a21f91bc23a 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -34,6 +34,7 @@ import com.ichi2.anki.model.SortType.EASE import com.ichi2.anki.model.SortType.NO_SORTING import com.ichi2.anki.model.SortType.SORT_FIELD import com.ichi2.anki.setFlagFilterSync +import com.ichi2.anki.utils.ext.ifNotZero import com.ichi2.libanki.Consts.QUEUE_TYPE_MANUALLY_BURIED import com.ichi2.libanki.Consts.QUEUE_TYPE_NEW import com.ichi2.libanki.Consts.QUEUE_TYPE_SUSPENDED @@ -529,6 +530,7 @@ class CardBrowserViewModelTest : JvmTest() { for (i in 0 until notes) { addNoteUsingBasicModel() } + notes.ifNotZero { count -> Timber.d("added %d notes", count) } val viewModel = CardBrowserViewModel( lastDeckIdRepository = SharedPreferencesLastDeckIdRepository(), cacheDir = createTransientDirectory(), diff --git a/AnkiDroid/src/test/java/com/ichi2/testutils/JvmTest.kt b/AnkiDroid/src/test/java/com/ichi2/testutils/JvmTest.kt index fad6d9de71ce..06d0ba95e427 100644 --- a/AnkiDroid/src/test/java/com/ichi2/testutils/JvmTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/testutils/JvmTest.kt @@ -65,10 +65,6 @@ open class JvmTest : TestClass { println("""-- executing test "${testName.methodName}"""") TimeManager.resetWith(MockTime(2020, 7, 7, 7, 0, 0, 0, 10)) - ChangeManager.clearSubscribers() - - maybeSetupBackend() - plant(object : Timber.DebugTree() { @SuppressLint("PrintStackTraceUsage") override fun log(priority: Int, tag: String?, message: String, t: Throwable?) { @@ -82,6 +78,10 @@ open class JvmTest : TestClass { } }) + ChangeManager.clearSubscribers() + + maybeSetupBackend() + Storage.setUseInMemory(true) } diff --git a/AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt b/AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt index e698a7462092..8e830d48f497 100644 --- a/AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt +++ b/AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt @@ -18,9 +18,8 @@ package com.ichi2.testutils import com.ichi2.libanki.ChangeManager import com.ichi2.libanki.undoableOp -import org.hamcrest.CoreMatchers.equalTo -import org.hamcrest.MatcherAssert.assertThat import timber.log.Timber +import kotlin.test.fail /** * Ensures no calls to [ChangeManager.notifySubscribers] via [undoableOp] @@ -33,7 +32,9 @@ suspend fun ensureNoOpsExecuted(block: suspend () -> Unit) { } block() // we should be fine to not cleanup here - assertThat("ChangeManager should not be called", !changes) + if (!changes) return + + fail("ChangeManager should not be called; ${ChangeManager.subscriberCount} subscribers") } /** @@ -47,6 +48,8 @@ suspend fun ensureOpsExecuted(count: Int, block: suspend () -> Unit) { } Timber.v("Listening for ChangeManager ops") block() + if (changes == count) return + // we should be fine to not cleanup here, as the subscriber goes out of scope - assertThat("ChangeManager: expected $count calls", changes, equalTo(count)) + fail("ChangeManager: expected $count calls; ${ChangeManager.subscriberCount} subscribers") } From 960951fb2757bdbb96a7deb79166ace6d8631347 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Tue, 4 Jun 2024 21:19:30 +0100 Subject: [PATCH 050/138] fix: close WorkManager test DB A number of errors were produced --- AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt index d4dcb1c23b08..062c64a36d41 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt @@ -189,6 +189,7 @@ open class RobolectricTest : AndroidTest { TimeManager.reset() } + WorkManagerTestInitHelper.closeWorkDatabase() Dispatchers.resetMain() runBlocking { CollectionManager.discardBackend() } println("""-- completed test "${testName.methodName}"""") From de409a5b9627429f2c7c354840e0e92a9c36e8b5 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Wed, 5 Jun 2024 10:58:27 +0100 Subject: [PATCH 051/138] fix(tests): change subscription - flaky This was caused because a WeakReference to the lambda was used, which went out of scope. This meant `changes` was not incremented CardBrowserViewModel: * suspend - notes - some cards suspended * suspend - notes - all suspended * etc... Fixes 16541 --- .../ichi2/testutils/TestChangeSubscriber.kt | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt b/AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt index 8e830d48f497..e03ff610e3e2 100644 --- a/AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt +++ b/AnkiDroid/src/test/java/com/ichi2/testutils/TestChangeSubscriber.kt @@ -16,6 +16,7 @@ package com.ichi2.testutils +import anki.collection.OpChanges import com.ichi2.libanki.ChangeManager import com.ichi2.libanki.undoableOp import timber.log.Timber @@ -25,14 +26,13 @@ import kotlin.test.fail * Ensures no calls to [ChangeManager.notifySubscribers] via [undoableOp] */ suspend fun ensureNoOpsExecuted(block: suspend () -> Unit) { - var changes = false - ChangeManager.subscribe { _, _ -> - Timber.d("ChangeManager op detected") - changes = true - } + val subscription = ChangeCounter() + ChangeManager.subscribe(subscription) block() - // we should be fine to not cleanup here - if (!changes) return + if (!subscription.hasChanges) { + Timber.d("ensureNoOpsExecuted: success") + return + } fail("ChangeManager should not be called; ${ChangeManager.subscriberCount} subscribers") } @@ -41,15 +41,26 @@ suspend fun ensureNoOpsExecuted(block: suspend () -> Unit) { * Ensures no calls to [ChangeManager.notifySubscribers] via [undoableOp] */ suspend fun ensureOpsExecuted(count: Int, block: suspend () -> Unit) { - var changes = 0 - ChangeManager.subscribe { _, _ -> - Timber.d("ChangeManager op detected") - changes++ - } + val subscription = ChangeCounter() + Timber.v("Listening for ChangeManager ops") + ChangeManager.subscribe(subscription) block() - if (changes == count) return + if (subscription.changeCount == count) { + Timber.d("ensureOpsExecuted: success") + return + } - // we should be fine to not cleanup here, as the subscriber goes out of scope fail("ChangeManager: expected $count calls; ${ChangeManager.subscriberCount} subscribers") } + +// used to ensure a strong reference to the subscription is held +private class ChangeCounter : ChangeManager.Subscriber { + private var changes = 0 + val changeCount get() = changes + val hasChanges get() = changes > 0 + override fun opExecuted(changes: OpChanges, handler: Any?) { + Timber.d("ChangeManager op detected") + this.changes++ + } +} From 8e1c71a54c06816887b3213d66c8e424d32cfc4f Mon Sep 17 00:00:00 2001 From: Moreno <154519856+morenotropical@users.noreply.github.com> Date: Wed, 5 Jun 2024 07:11:24 -0300 Subject: [PATCH 052/138] use appcompat AlertDialog --- .../com/ichi2/anki/analytics/AnkiDroidCrashReportDialog.kt | 2 +- .../com/ichi2/anki/dialogs/MigrationProgressDialogFragment.kt | 4 ++-- .../java/com/ichi2/anki/dialogs/TtsVoicesDialogFragment.kt | 4 ++-- .../anki/multimediacard/activity/PickStringDialogFragment.kt | 4 ++-- .../main/java/com/ichi2/anki/ui/dialogs/tools/AsyncDialogs.kt | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/analytics/AnkiDroidCrashReportDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/analytics/AnkiDroidCrashReportDialog.kt index 0b4199fa8460..ffd99d0c6f19 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/analytics/AnkiDroidCrashReportDialog.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/analytics/AnkiDroidCrashReportDialog.kt @@ -17,12 +17,12 @@ package com.ichi2.anki.analytics import android.annotation.SuppressLint -import android.app.AlertDialog import android.content.DialogInterface import android.os.Bundle import android.view.View import android.widget.CheckBox import android.widget.EditText +import androidx.appcompat.app.AlertDialog import androidx.core.content.edit import com.ichi2.anki.CrashReportService import com.ichi2.anki.R diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MigrationProgressDialogFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MigrationProgressDialogFragment.kt index d1f107510df6..a30746c8348a 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MigrationProgressDialogFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MigrationProgressDialogFragment.kt @@ -16,11 +16,11 @@ package com.ichi2.anki.dialogs -import android.app.AlertDialog import android.app.Dialog import android.os.Bundle import android.text.format.Formatter.formatShortFileSize import android.widget.TextView +import androidx.appcompat.app.AlertDialog import androidx.fragment.app.DialogFragment import androidx.lifecycle.Lifecycle import androidx.lifecycle.flowWithLifecycle @@ -85,7 +85,7 @@ class MigrationProgressDialogFragment : DialogFragment() { } } - return AlertDialog.Builder(activity) + return AlertDialog.Builder(requireActivity()) .setView(layout) .setPositiveButton(R.string.dialog_ok) { _, _ -> dismiss() } .setNegativeButton(R.string.scoped_storage_learn_more) { _, _ -> diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/TtsVoicesDialogFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/TtsVoicesDialogFragment.kt index 1a79864542aa..4c0324f1d8cf 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/TtsVoicesDialogFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/TtsVoicesDialogFragment.kt @@ -16,7 +16,6 @@ package com.ichi2.anki.dialogs -import android.app.AlertDialog import android.content.ActivityNotFoundException import android.content.Intent import android.content.res.ColorStateList @@ -28,6 +27,7 @@ import android.view.ViewGroup import android.widget.Button import android.widget.EditText import android.widget.TextView +import androidx.appcompat.app.AlertDialog import androidx.core.widget.doOnTextChanged import androidx.fragment.app.DialogFragment import androidx.fragment.app.viewModels @@ -160,7 +160,7 @@ class TtsVoicesDialogFragment : DialogFragment() { viewModel.availableVoicesFlow.observe { if (it is TtsVoicesViewModel.VoiceLoadingState.Failure) { progressBar.visibility = View.VISIBLE - AlertDialog.Builder(this.context) + AlertDialog.Builder(requireContext()) .setMessage(it.exception.localizedMessage) .setOnDismissListener { this@TtsVoicesDialogFragment.dismiss() } .show() diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/multimediacard/activity/PickStringDialogFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/multimediacard/activity/PickStringDialogFragment.kt index 830b1912a77d..fa3993e82181 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/multimediacard/activity/PickStringDialogFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/multimediacard/activity/PickStringDialogFragment.kt @@ -20,11 +20,11 @@ package com.ichi2.anki.multimediacard.activity import android.R -import android.app.AlertDialog import android.app.Dialog import android.content.DialogInterface import android.os.Bundle import android.widget.ArrayAdapter +import androidx.appcompat.app.AlertDialog import androidx.fragment.app.DialogFragment import com.ichi2.utils.KotlinCleanup import java.util.* @@ -40,7 +40,7 @@ class PickStringDialogFragment : DialogFragment() { @KotlinCleanup("requireActivity") override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { // Use the Builder class for convenient dialog construction - val builder = AlertDialog.Builder(activity) + val builder = AlertDialog.Builder(requireActivity()) builder.setTitle(title) val adapter = ArrayAdapter( requireActivity(), diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/dialogs/tools/AsyncDialogs.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/dialogs/tools/AsyncDialogs.kt index b457e3237fb4..76ae278374c4 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/dialogs/tools/AsyncDialogs.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/dialogs/tools/AsyncDialogs.kt @@ -14,10 +14,10 @@ package com.ichi2.anki.ui.dialogs.tools -import android.app.AlertDialog import android.content.Context import android.content.DialogInterface.BUTTON_POSITIVE import androidx.annotation.StringRes +import androidx.appcompat.app.AlertDialog import kotlinx.coroutines.suspendCancellableCoroutine import kotlin.coroutines.Continuation import kotlin.coroutines.resume From 5c89baba406f3ac10c623707e913ecf00ec628bb Mon Sep 17 00:00:00 2001 From: Sumit Singh Date: Wed, 5 Jun 2024 18:16:21 +0530 Subject: [PATCH 053/138] lint to avoid using android.app.AlertDialog --- .../java/com/ichi2/anki/lint/IssueRegistry.kt | 4 +- .../anki/lint/rules/AvoidAlertDialogUsage.kt | 81 +++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 lint-rules/src/main/java/com/ichi2/anki/lint/rules/AvoidAlertDialogUsage.kt diff --git a/lint-rules/src/main/java/com/ichi2/anki/lint/IssueRegistry.kt b/lint-rules/src/main/java/com/ichi2/anki/lint/IssueRegistry.kt index 9a78b0088f69..df21649549a1 100644 --- a/lint-rules/src/main/java/com/ichi2/anki/lint/IssueRegistry.kt +++ b/lint-rules/src/main/java/com/ichi2/anki/lint/IssueRegistry.kt @@ -21,6 +21,7 @@ import com.android.tools.lint.client.api.IssueRegistry import com.android.tools.lint.client.api.Vendor import com.android.tools.lint.detector.api.CURRENT_API import com.android.tools.lint.detector.api.Issue +import com.ichi2.anki.lint.rules.AvoidAlertDialogUsage import com.ichi2.anki.lint.rules.CopyrightHeaderExists import com.ichi2.anki.lint.rules.DirectCalendarInstanceUsage import com.ichi2.anki.lint.rules.DirectDateInstantiation @@ -62,7 +63,8 @@ class IssueRegistry : IssueRegistry() { FixedPreferencesTitleLength.ISSUE_MAX_LENGTH, FixedPreferencesTitleLength.ISSUE_TITLE_LENGTH, VariableNamingDetector.ISSUE, - InvalidStringFormatDetector.ISSUE + InvalidStringFormatDetector.ISSUE, + AvoidAlertDialogUsage.ISSUE ) } override val api: Int diff --git a/lint-rules/src/main/java/com/ichi2/anki/lint/rules/AvoidAlertDialogUsage.kt b/lint-rules/src/main/java/com/ichi2/anki/lint/rules/AvoidAlertDialogUsage.kt new file mode 100644 index 000000000000..48fa2e45a84c --- /dev/null +++ b/lint-rules/src/main/java/com/ichi2/anki/lint/rules/AvoidAlertDialogUsage.kt @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2024 Sumit Singh + * + * 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 . + */ +@file:Suppress("UnstableApiUsage") + +package com.ichi2.anki.lint.rules + +import com.android.tools.lint.client.api.UElementHandler +import com.android.tools.lint.detector.api.* +import com.google.common.annotations.VisibleForTesting +import com.ichi2.anki.lint.utils.Constants +import org.jetbrains.uast.UElement +import org.jetbrains.uast.UImportStatement + +/** + * This custom Lint rule raises a warning if a developer uses the `android.app.AlertDialog` class. + */ +class AvoidAlertDialogUsage : Detector(), SourceCodeScanner { + + companion object { + @VisibleForTesting + const val ID = "AvoidAlertDialogUsage" + + @VisibleForTesting + const val DESCRIPTION = "Use androidx.appcompat.app.AlertDialog instead of android.app.AlertDialog" + private const val EXPLANATION = "Using `android.app.AlertDialog` is discouraged. " + + "Please use `androidx.appcompat.app.AlertDialog` instead for better compatibility and features." + private val implementation = Implementation(AvoidAlertDialogUsage::class.java, Scope.JAVA_FILE_SCOPE) + val ISSUE: Issue = Issue.create( + ID, + DESCRIPTION, + EXPLANATION, + Constants.ANKI_TIME_CATEGORY, + Constants.ANKI_TIME_PRIORITY, + Constants.ANKI_TIME_SEVERITY, + implementation + ) + } + + override fun getApplicableUastTypes(): List> { + return listOf(UImportStatement::class.java) + } + + override fun createUastHandler(context: JavaContext): UElementHandler { + return object : UElementHandler() { + override fun visitImportStatement(node: UImportStatement) { + val importReference = node.asSourceString() + if (importReference.contains("android.app.AlertDialog")) { + context.report( + ISSUE, + node, + context.getLocation(node), + DESCRIPTION, + createFix() + ) + } + } + } + } + + private fun createFix(): LintFix { + return fix() + .name("Replace with androidx.appcompat.app.AlertDialog") + .replace() + .text("android.app.AlertDialog") + .with("androidx.appcompat.app.AlertDialog") + .build() + } +} From 149116c45b4a9076f638675a27b90bbf164fecbe Mon Sep 17 00:00:00 2001 From: Robozinho <65715921+robozinhod@users.noreply.github.com> Date: Tue, 4 Jun 2024 20:28:38 -0300 Subject: [PATCH 054/138] =?UTF-8?q?Productionise=20webview=20=E2=89=A5=207?= =?UTF-8?q?7=20check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes 15855 Co-authored-by: aayush-tripathi <112811133+aayush-tripathi@users.noreply.github.com> --- .../main/java/com/ichi2/anki/DeckPicker.kt | 26 +---------- .../java/com/ichi2/anki/InitialActivity.kt | 43 +++++++++++++++++++ AnkiDroid/src/main/res/values/03-dialogs.xml | 2 + AnkiDroid/src/main/res/values/constants.xml | 2 + 4 files changed, 49 insertions(+), 24 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt b/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt index 4c74215bf772..5e9245139304 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt @@ -519,9 +519,8 @@ open class DeckPicker : Onboarding.DeckPicker(this, recyclerViewLayoutManager).onCreate() launchShowingHidingEssentialFileMigrationProgressDialog() - if (BuildConfig.DEBUG) { - checkWebviewVersion() - } + + InitialActivity.checkWebviewVersion(packageManager, this) supportFragmentManager.setFragmentResultListener(DeckPickerContextMenu.REQUEST_KEY_CONTEXT_MENU, this) { requestKey, arguments -> when (requestKey) { @@ -615,27 +614,6 @@ open class DeckPicker : } } - /** - * Check if the current WebView version is older than the last supported version and if it is, - * inform the developer with a snackbar. - */ - private fun checkWebviewVersion() { - // Doesn't need to be translated as it's debug only - val webviewPackageInfo = getAndroidSystemWebViewPackageInfo(packageManager) - if (webviewPackageInfo == null) { - val snackbarMessage = "No Android System WebView found" - postSnackbar(snackbarMessage, Snackbar.LENGTH_INDEFINITE) - return - } - - val versionCode = webviewPackageInfo.versionName.split(".")[0].toInt() - if (versionCode < OLDEST_WORKING_WEBVIEW_VERSION) { - val snackbarMessage = - "The WebView version $versionCode is outdated (<$OLDEST_WORKING_WEBVIEW_VERSION)." - postSnackbar(snackbarMessage, Snackbar.LENGTH_INDEFINITE) - } - } - /** * The first call in showing dialogs for startup * diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/InitialActivity.kt b/AnkiDroid/src/main/java/com/ichi2/anki/InitialActivity.kt index 1589e60b5830..d27def0f0730 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/InitialActivity.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/InitialActivity.kt @@ -18,12 +18,15 @@ package com.ichi2.anki import android.content.Context import android.content.SharedPreferences +import android.content.pm.PackageInfo +import android.content.pm.PackageManager import android.database.sqlite.SQLiteFullException import android.os.Build import android.os.Environment import android.os.Parcelable import androidx.annotation.CheckResult import androidx.annotation.RequiresApi +import androidx.appcompat.app.AlertDialog import androidx.core.content.edit import com.ichi2.anki.servicelayer.PreferenceUpgradeService import com.ichi2.anki.servicelayer.PreferenceUpgradeService.setPreferencesUpToDate @@ -34,6 +37,8 @@ import com.ichi2.anki.ui.windows.permissions.PermissionsUntil29Fragment import com.ichi2.anki.ui.windows.permissions.TiramisuPermissionsFragment import com.ichi2.utils.Permissions import com.ichi2.utils.VersionUtils.pkgVersionName +import com.ichi2.utils.getAndroidSystemWebViewPackageInfo +import com.ichi2.utils.show import kotlinx.parcelize.Parcelize import net.ankiweb.rsdroid.BackendException import timber.log.Timber @@ -133,6 +138,44 @@ object InitialActivity { SD_CARD_NOT_MOUNTED, DIRECTORY_NOT_ACCESSIBLE, FUTURE_ANKIDROID_VERSION, DB_ERROR, DATABASE_LOCKED, WEBVIEW_FAILED, DISK_FULL } + + /** + * Shows a dialog if the current WebView version is older than the last supported version. + */ + fun checkWebviewVersion(packageManager: PackageManager, activity: AnkiActivity) { + val webviewPackageInfo = getAndroidSystemWebViewPackageInfo(packageManager) ?: return + val versionCode = webviewPackageInfo.versionName.split(".")[0].toInt() + if (versionCode >= OLDEST_WORKING_WEBVIEW_VERSION) { + Timber.d("WebView is up to date. %s: %s", webviewPackageInfo.packageName, webviewPackageInfo.versionName) + return + } + + val legacyWebViewPackageInfo = getLegacyWebViewPackageInfo(packageManager) + if (legacyWebViewPackageInfo != null) { + Timber.w("WebView is outdated. %s: %s", legacyWebViewPackageInfo.packageName, legacyWebViewPackageInfo.versionName) + showOutdatedWebViewDialog(activity, versionCode, activity.getString(R.string.link_legacy_webview_update)) + } else { + Timber.w("WebView is outdated. %s: %s", webviewPackageInfo.packageName, webviewPackageInfo.versionName) + showOutdatedWebViewDialog(activity, versionCode, activity.getString(R.string.link_webview_update)) + } + } + + private fun showOutdatedWebViewDialog(activity: AnkiActivity, installedVersion: Int, learnMoreUrl: String) { + AlertDialog.Builder(activity).show { + setMessage(activity.getString(R.string.webview_update_message, installedVersion, OLDEST_WORKING_WEBVIEW_VERSION)) + setPositiveButton(R.string.scoped_storage_learn_more) { _, _ -> + activity.openUrl(learnMoreUrl) + } + } + } + + private fun getLegacyWebViewPackageInfo(packageManager: PackageManager): PackageInfo? { + return try { + packageManager.getPackageInfo("com.android.webview", 0) + } catch (e: PackageManager.NameNotFoundException) { + null + } + } } sealed class AnkiDroidFolder(val permissionSet: PermissionSet) { diff --git a/AnkiDroid/src/main/res/values/03-dialogs.xml b/AnkiDroid/src/main/res/values/03-dialogs.xml index 1878f2b30b0b..f95925fbcaf1 100644 --- a/AnkiDroid/src/main/res/values/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values/03-dialogs.xml @@ -277,4 +277,6 @@ also changes the interval of the card" Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values/constants.xml b/AnkiDroid/src/main/res/values/constants.xml index c1d48a875fa0..a63dc1b90bd7 100644 --- a/AnkiDroid/src/main/res/values/constants.xml +++ b/AnkiDroid/src/main/res/values/constants.xml @@ -139,6 +139,8 @@ https://github.com/ankidroid/Anki-Android/wiki/Privacy-Policy https://ankiweb.net/account/privacy https://ankiweb.net/account/terms + https://github.com/ankidroid/Anki-Android/wiki/WebView-Detection-and-Package-Updates#outdated-webview + https://github.com/ankidroid/Anki-Android/wiki/WebView-Detection-and-Package-Updates#outdated-android-native-webview https://discord.gg/qjzcRTx https://www.facebook.com/AnkiDroid/ From b01fdd3a45070a768ac992c72286ba961118cbee Mon Sep 17 00:00:00 2001 From: AnkiDroid Translations Date: Wed, 5 Jun 2024 16:15:16 +0000 Subject: [PATCH 055/138] Updated strings from Crowdin --- .../src/main/res/values-de/03-dialogs.xml | 6 +- .../src/main/res/values-gu/02-strings.xml | 354 +++++++++--------- .../src/main/res/values-zh-rCN/03-dialogs.xml | 8 +- 3 files changed, 184 insertions(+), 184 deletions(-) diff --git a/AnkiDroid/src/main/res/values-de/03-dialogs.xml b/AnkiDroid/src/main/res/values-de/03-dialogs.xml index e3b1073db017..e9c5d13c41ba 100644 --- a/AnkiDroid/src/main/res/values-de/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-de/03-dialogs.xml @@ -251,8 +251,8 @@ Von Bis - Cloze Type Note Required - No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. - Open + Cloze-Notiztyp erforderlich + Kein Cloze-Notiztyp gefunden. Öffnen Sie den Notiz-Editor oder versuchen Sie es erneut, nachdem Sie einen Cloze-Notiztyp hinzugefügt haben. + Offen Single tap text to cloze diff --git a/AnkiDroid/src/main/res/values-gu/02-strings.xml b/AnkiDroid/src/main/res/values-gu/02-strings.xml index b1745559e65b..4824ac23d6ab 100644 --- a/AnkiDroid/src/main/res/values-gu/02-strings.xml +++ b/AnkiDroid/src/main/res/values-gu/02-strings.xml @@ -77,13 +77,13 @@ મેમરી બહાર વેબવ્યુ સિસ્ટમ દ્વારા સમાપ્ત કરવામાં આવ્યું હતું. આ સામાન્ય રીતે થાય છે જ્યારે એપ્લિકેશનની મેમરી સમાપ્ત થઈ જાય છે, મોટાભાગે મોટા ફોન્ટ્સ અથવા મીડિયાને કારણે. WebView રેન્ડરર ક્રેશ થયું. કારણ: %s - Fatal Error: WebView renderer crashed. Cause: %s - System WebView Rendering Failure - System WebView failed to render card \'%1$s\'.\n %2$s + જીવલેણ ભૂલ: WebView રેન્ડરર ક્રેશ થયું. કારણ: %s + સિસ્ટમ વેબ વ્યૂ રેન્ડરિંગ નિષ્ફળતા + સિસ્ટમ WebView કાર્ડ \'%1$s\' રેન્ડર કરવામાં નિષ્ફળ થયું.\n %2$s - Question - Sort field + પ્રશ્ન + સૉર્ટ ક્ષેત્ર જવાબ આપો @@ -91,197 +91,197 @@ તૂતક નૉૅધ પ્રશ્ન - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified + ટૅગ્સ + ક્ષતિઓ + સમીક્ષાઓ + અંતરાલ + સરળતા + બાકી + કાર્ડ સંશોધિત + બનાવ્યું + નોંધ સંશોધિત - Flags + ધ્વજ - Modify today’s new card limit - Modify today’s review card limit - Review forgotten cards - Review ahead - Study a random selection of cards - Preview new cards - Limit to particular tags + આજની નવી કાર્ડ મર્યાદામાં ફેરફાર કરો + આજની સમીક્ષા કાર્ડ મર્યાદામાં ફેરફાર કરો + ભૂલી ગયેલા કાર્ડ્સની સમીક્ષા કરો + આગળ સમીક્ષા કરો + કાર્ડ્સની રેન્ડમ પસંદગીનો અભ્યાસ કરો + નવા કાર્ડ્સનું પૂર્વાવલોકન કરો + ચોક્કસ ટૅગ્સ સુધી મર્યાદિત કરો - Edit note - Discard - No cards created. Please fill in more fields - The current note type did not produce any cards.\nPlease choose another note type, or click ‘Cards’ and add a field substitution - Cloze deletions will only work on a Cloze note type - Saving note - Saving note type - Save - Close + નોંધ સંપાદિત કરો + રદ્દ કરો + કોઈ કાર્ડ બનાવ્યા નથી. કૃપા કરીને વધુ ફીલ્ડ ભરો + વર્તમાન નોંધ પ્રકારે કોઈ કાર્ડ બનાવ્યા નથી.\nકૃપા કરીને અન્ય નોંધ પ્રકાર પસંદ કરો અથવા \'કાર્ડ્સ\' પર ક્લિક કરો અને ફીલ્ડ અવેજી ઉમેરો + ક્લોઝ ડિલીટ માત્ર ક્લોઝ નોટ પ્રકાર પર જ કામ કરશે + નોંધ સાચવી રહ્યા છીએ + નોંધનો પ્રકાર સાચવી રહ્યું છે + સેવ કરો + બંધ પસંદ કરો %1$s (“%2$s”માંથી) - Any cards mapped to nothing will be deleted. If a note has no remaining cards, it will be lost. Are you sure you want to continue? + કંઈપણ સાથે મેપ કરેલ કોઈપણ કાર્ડ કાઢી નાખવામાં આવશે. જો કોઈ નોંધમાં કોઈ બાકી કાર્ડ નથી, તો તે ખોવાઈ જશે. શું તમે ખરેખર ચાલુ રાખવા માંગો છો? કોઈ નોંધ પ્રકાર મળ્યો નથી - Timebox reached + ટાઈમબોક્સ પહોંચી ગયું - %1$d card studied in %2$s - %1$d cards studied in %2$s + %2$s માં %1$d કાર્ડનો અભ્યાસ કર્યો + %2$s માં %1$d કાર્ડ્સનો અભ્યાસ કર્યો - %1$d minute - %1$d minutes + %1$d મિનિટ + %1$d મિનિટ - AnkiDroid card - Copy note - Reposition - Reset progress - Reschedule - Preview - Copy as Markdown - %1$d of %2$d - Rename - Check - Check database - Check media - Empty cards - This card is empty. Use the “Empty cards” option from the menu on the deck list screen. - Type answer: unknown field %s - Deleting deck… - Rate AnkiDroid - Importing - Add - This will delete your existing collection and replace it with the data of file %s - Add “%s” to collection? This may take a long time - This isn’t a valid Anki package file - Error - Failed to import file\n\n%s - Filename “%s” doesn’t have .apkg or .colpkg extension - Anki Database (.anki2) replacements are not yet supported. Please see the manual for replacement instructions. - The selected file couldn’t be imported automatically by AnkiDroid. Please see the user manual for how to manually import anki files: \n%s - Failed to cache file (possibly out of storage space) - Import interrupted: AnkiDroid was closed - Preparing export… - Export ready - No applications available to handle apkg. Saving… - Successfully saved Anki package - Save Anki package failed - Send Anki package using - AnkiDroid exported flashcards: %s - AnkiDroid કાર્ડ + નોંધની નકલ કરો + રિપોઝિશન + પ્રગતિ રીસેટ કરો + ફરીથી શેડ્યૂલ કરો + પૂર્વાવલોકન કરો + માર્કડાઉન તરીકે કૉપિ કરો + %1$d માંથી %2$d + નામ બદલો + તપાસ + ડેટાબેઝ તપાસો + મીડિયા તપાસો + ખાલી કાર્ડ્સ + આ કાર્ડ ખાલી છે. ડેક સૂચિ સ્ક્રીન પરના મેનૂમાંથી \"ખાલી કાર્ડ્સ\" વિકલ્પનો ઉપયોગ કરો. + જવાબ લખો: અજ્ઞાત ફીલ્ડ %s + ડેક કાઢી રહ્યું છે… + AnkiDroid ને રેટ કરો + આયાત કરી રહ્યું છે + ઉમેરો + આ તમારા વર્તમાન સંગ્રહને કાઢી નાખશે અને તેને ફાઇલ %s ના ડેટા સાથે બદલશે + સંગ્રહમાં “%s” ઉમેરીએ? આમાં ઘણો સમય લાગી શકે છે + આ માન્ય અંકી પેકેજ ફાઇલ નથી + ભૂલ + ફાઇલ આયાત કરવામાં નિષ્ફળ\n\n%s + ફાઇલનામ “%s” માં .apkg અથવા .colpkg એક્સ્ટેંશન નથી + Anki Database (.anki2) રિપ્લેસમેન્ટ હજુ સુધી સપોર્ટેડ નથી. કૃપા કરીને રિપ્લેસમેન્ટ સૂચનાઓ માટે મેન્યુઅલ જુઓ. + પસંદ કરેલી ફાઇલ AnkiDroid દ્વારા આપમેળે આયાત કરી શકાઈ નથી. એન્કી ફાઇલોને મેન્યુઅલી કેવી રીતે આયાત કરવી તે માટે કૃપા કરીને વપરાશકર્તા માર્ગદર્શિકા જુઓ: \n%s + ફાઇલ કેશ કરવામાં નિષ્ફળ (કદાચ સ્ટોરેજ સ્પેસની બહાર) + આયાત વિક્ષેપિત: AnkiDroid બંધ હતું + નિકાસની તૈયારી કરી રહ્યાં છીએ… + નિકાસ તૈયાર છે + apkg હેન્ડલ કરવા માટે કોઈ એપ્લિકેશન ઉપલબ્ધ નથી. સાચવી રહ્યું છે… + અંકી પેકેજ સફળતાપૂર્વક સાચવ્યું + અંકી પેકેજને સાચવવાનું નિષ્ફળ થયું + ઉપયોગ કરીને Anki પેકેજ મોકલો + AnkiDroid એ નિકાસ કરેલા ફ્લેશકાર્ડ્સ: %s +
- This is an Anki flashcards deck sent from AnkiDroid[1]. - Try to open it using one of the available Anki distributions[2] and enjoy easy and efficient learning!

+ આ AnkiDroid[1] તરફથી મોકલવામાં આવેલ અંકી ફ્લેશકાર્ડ્સ ડેક છે. + ઉપલબ્ધ અંકી વિતરણોમાંથી એકનો ઉપયોગ કરીને તેને ખોલવાનો પ્રયાસ કરો[2] અને સરળ અને કાર્યક્ષમ શિક્ષણનો આનંદ માણો!

[1] %1$s
[2] %2$s ]]>
- Share - Save to - Options - Deck options - Study options - Set TTS language - Custom study - More - This is a special deck for studying outside of the normal schedule. Cards will be automatically returned to their original decks after you review them. Deleting this deck from the deck list will return all remaining cards to their original deck. - Steps must be numbers greater than 0 - At least one step is required - Touch “%2$s” to confirm adding “%1$s” - Existing tag “%1$s” selected + શેર કરો + આના પર સાચવો + વિકલ્પો + ડેક વિકલ્પો + અભ્યાસ વિકલ્પો + TTS ભાષા સેટ કરો + કસ્ટમ અભ્યાસ + વધુ + સામાન્ય સમયપત્રકની બહાર અભ્યાસ કરવા માટે આ એક ખાસ ડેક છે. તમે તેમની સમીક્ષા કર્યા પછી કાર્ડ્સ આપમેળે તેમના મૂળ ડેક પર પાછા આવશે. ડેક સૂચિમાંથી આ ડેકને કાઢી નાખવાથી બાકીના તમામ કાર્ડ્સ તેમના મૂળ ડેક પર પાછા આવશે. + પગલાંની સંખ્યા 0 કરતાં મોટી હોવી જોઈએ + ઓછામાં ઓછું એક પગલું જરૂરી છે + \"%1$s\" ઉમેરવાની પુષ્ટિ કરવા માટે \"%2$s\" ને ટચ કરો + હાલનું ટૅગ “%1$s” પસંદ કર્યું - Do not forget to study today! + આજે અભ્યાસ કરવાનું ભૂલશો નહીં! - %2$d card to review in %1$s - %2$d cards to review in %1$s + %1$s માં સમીક્ષા કરવા માટે %2$d કાર્ડ + %1$s માં સમીક્ષા કરવા માટે %2$d કાર્ડ - Error sharing apkg file + apkg ફાઇલ શેર કરવામાં ભૂલ - The system does not have an app installed that can perform this action. - - No browser found for opening the link: %s - Error loading page: %s + સિસ્ટમમાં કોઈ એપ ઇન્સ્ટોલ કરેલી નથી જે આ ક્રિયા કરી શકે. + + લિંક ખોલવા માટે કોઈ બ્રાઉઝર મળ્યું નથી: %s + પૃષ્ઠ લોડ કરવામાં ભૂલ: %s - Background - Select image - Remove background? + પૃષ્ઠભૂમિ + છબી પસંદ કરો + પૃષ્ઠભૂમિ દૂર કરીએ? - Restore Default - Blank + મૂળભૂત પુનઃસ્થાપિત + ખાલી - Failed to save whiteboard image. %s - Whiteboard image saved to %s - Whiteboard pen color - Whiteboard editor - Detected automated test. If you are a human, contact AnkiDroid support + વ્હાઇટબોર્ડ છબી સાચવવામાં નિષ્ફળ. %s + વ્હાઇટબોર્ડ ઇમેજ %s પર સાચવી + વ્હાઇટબોર્ડ પેન રંગ + વ્હાઇટબોર્ડ એડિટર + શોધાયેલ સ્વચાલિત પરીક્ષણ. જો તમે માનવ છો, તો AnkiDroid સપોર્ટનો સંપર્ક કરો - This card uses unsupported AnkiDroid features. Contact developer %1$s, or view the wiki. %2$s - Card provided invalid data. %s - Invalid AnkiDroid JS API version. Contact developer %s, or view wiki - AnkiDroid JS API update available. Contact developer %s, or view wiki - View - (Error Code: %d) + આ કાર્ડ અસમર્થિત AnkiDroid સુવિધાઓનો ઉપયોગ કરે છે. વિકાસકર્તા %1$s નો સંપર્ક કરો અથવા વિકિ જુઓ. %2$s + કાર્ડ અમાન્ય ડેટા પ્રદાન કરે છે. %s + અમાન્ય AnkiDroid JS API સંસ્કરણ. વિકાસકર્તા %s નો સંપર્ક કરો અથવા વિકિ જુઓ + AnkiDroid JS API અપડેટ ઉપલબ્ધ છે. વિકાસકર્તા %s નો સંપર્ક કરો અથવા વિકિ જુઓ + જુઓ + (ભૂલ કોડ: %d) - Copied to clipboard - Error copying debug information to clipboard + ક્લિપબોર્ડ પર કૉપિ કરી + ડિબગ માહિતીને ક્લિપબોર્ડ પર કૉપિ કરવામાં ભૂલ - Card Content Error: Failed to load ‘%s’ + કાર્ડ સામગ્રી ભૂલ: \'%s\' લોડ કરવામાં નિષ્ફળ - Search decks - Show migration progress - Fatal Error - AnkiDroid relies on the System WebView which is unavailable. This can happen if the system is installing updates. Please try again in a few minutes.\n\n%s + તૂતક શોધો + સ્થળાંતર પ્રગતિ બતાવો + જીવલેણ ભૂલ + AnkiDroid સિસ્ટમ WebView પર આધાર રાખે છે જે અનુપલબ્ધ છે. જો સિસ્ટમ અપડેટ્સ ઇન્સ્ટોલ કરી રહી હોય તો આ થઈ શકે છે. કૃપા કરીને થોડીવારમાં ફરી પ્રયાસ કરો.\n\n%s - Font size - Show toolbar - Format as Bold - Format as Italic - Format as Underline - Insert Horizontal Line - Insert Heading - Change Font Size - Insert MathJax Equation - Button text - HTML Before Selection - HTML After Selection - Create Toolbar Item - Edit Toolbar Item - Enter HTML to be inserted before and after the selected text\n\nLong press a toolbar item to edit or remove it - Remove Toolbar Item? - The image is too large to paste, please insert the image manually - Android backup in progress. Please try again - You may need to use iManager to allow AnkiDroid to add shortcuts - Your home screen does not allow AnkiDroid to add shortcuts - Error adding shortcut: %s - Capitalize sentences - Scroll toolbar + અક્ષર ની જાડાઈ + ટૂલબાર બતાવો + બોલ્ડ તરીકે ફોર્મેટ કરો + ઇટાલિક તરીકે ફોર્મેટ કરો + અન્ડરલાઇન તરીકે ફોર્મેટ કરો + આડી રેખા દાખલ કરો + શીર્ષક દાખલ કરો + ફોન્ટનું કદ બદલો + MathJax સમીકરણ દાખલ કરો + બટન ટેક્સ્ટ + પસંદગી પહેલાં HTML + પસંદગી પછી HTML + ટૂલબાર આઇટમ બનાવો + ટૂલબાર આઇટમ સંપાદિત કરો + પસંદ કરેલ ટેક્સ્ટ પહેલાં અને પછી દાખલ કરવા માટે HTML દાખલ કરો\n\nટૂલબાર આઇટમને સંપાદિત કરવા અથવા દૂર કરવા માટે તેને લાંબા સમય સુધી દબાવો + ટૂલબાર આઇટમ દૂર કરીએ? + છબી પેસ્ટ કરવા માટે ખૂબ મોટી છે, કૃપા કરીને મેન્યુઅલી છબી દાખલ કરો + Android બેકઅપ ચાલુ છે. મહેરબાની કરીને ફરીથી પ્રયતન કરો + AnkiDroid ને શૉર્ટકટ્સ ઉમેરવાની મંજૂરી આપવા માટે તમારે iManager નો ઉપયોગ કરવાની જરૂર પડી શકે છે + તમારી હોમ સ્ક્રીન AnkiDroid ને શોર્ટકટ ઉમેરવાની મંજૂરી આપતી નથી + શૉર્ટકટ ઉમેરવામાં ભૂલ: %s + વાક્યોને કેપિટલાઇઝ કરો + ટૂલબારને સ્ક્રોલ કરો + - - Enter a valid email - Password is required - Press back again to exit - Press back again to return + માન્ય ઇમેઇલ દાખલ કરો + પાસવર્ડ અનિવાર્ય છે + બહાર નીકળવા માટે ફરીથી પાછા દબાવો + પાછા આવવા માટે ફરીથી પાછા દબાવો %s%% - Download deck - Try Again - Cancel download - Cancel download? - Downloading %s - Import Deck - Something went wrong, please try again - Download failed - You can use other apps while the download is running - Please check your network connection - Search using deck name - Download aborted, the external storage is not available - Home + ડેક ડાઉનલોડ કરો + ફરીથી પ્રયત્ન કરો + ડાઉનલોડ રદ કરો + ડાઉનલોડ રદ કરીએ? + %s ડાઉનલોડ થાય છે + આયાત ડેક + કંઈક ખોટું થયું, કૃપા કરીને ફરી પ્રયાસ કરો + ડાઉનલોડ ફેઇલ ગયું છે + ડાઉનલોડ ચાલુ હોય ત્યારે તમે અન્ય એપ્સનો ઉપયોગ કરી શકો છો + કૃપા કરીને તમારું નેટવર્ક કનેક્શન તપાસો + ડેક નામનો ઉપયોગ કરીને શોધો + ડાઉનલોડ રદ કર્યું, બાહ્ય સ્ટોરેજ ઉપલબ્ધ નથી + ઘર Card buried. @@ -342,29 +342,29 @@ Deleting selected notes Tap a voice to listen - Voice should be installed before use + ઉપયોગ કરતા પહેલા વૉઇસ ઇન્સ્ટોલ થવો જોઈએ - Use anyway + કોઈપણ રીતે ઉપયોગ કરો - Text to speech error (%s) + ટેક્સ્ટ ટુ સ્પીચ ભૂલ (%s) - Internet + ઈન્ટરનેટ - Install + ઇન્સ્ટોલ કરો - Failed to open text to speech settings + ટેક્સ્ટ ટુ સ્પીચ સેટિંગ્સ ખોલવામાં નિષ્ફળ - Please log in to download more decks - Description - Failed to copy - Unavailable in ‘Notes’ mode + વધુ ડેક ડાઉનલોડ કરવા માટે કૃપા કરીને લૉગ ઇન કરો + વર્ણન + કૉપિ કરવામાં નિષ્ફળ + \'નોટ્સ\' મોડમાં અનુપલબ્ધ - %d card unburied - %d cards unburied + %d કાર્ડ અનબરી + %d કાર્ડ અનબરી - Reposition - Record - Stop - Play - Next + રિપોઝિશન + રેકોર્ડ કરો + બંધ + પ્લે + આગલું diff --git a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml index 3b73d140f96a..47aa2f483f2b 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml @@ -245,8 +245,8 @@ - Cloze Type Note Required - No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. - Open - Single tap text to cloze + 需要Cloze类型笔记 + 未找到Cloze类型笔记,打开笔记编辑器或添加Cloze类型笔记后重试。 + 打开 + 要关闭,请轻按一次文本 From 3675f72ababa5e4df1d906f28bb0cd3d255e1336 Mon Sep 17 00:00:00 2001 From: AnkiDroid Translations Date: Wed, 5 Jun 2024 17:11:08 +0000 Subject: [PATCH 056/138] Updated strings from Crowdin --- AnkiDroid/src/main/res/values-af/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-am/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ar/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-az/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-be/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-bg/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-bn/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ca/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ckb/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-cs/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-da/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-de/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-el/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-eo/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-et/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-eu/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-fa/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-fi/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-fil/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-fr/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-fy/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ga/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-gl/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-got/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-gu/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-heb/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-hi/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-hr/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-hu/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-hy/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ind/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-is/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-it/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-iw/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ja/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-jv/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ka/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-kk/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-km/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-kn/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ko/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ku/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ky/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-lt/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-lv/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-mk/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ml/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-mn/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-mr/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ms/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-my/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-nl/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-nn/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-no/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-or/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-pa/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-pl/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ro/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ru/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sat/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sc/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sk/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sl/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sq/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sr/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ss/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sv/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sw/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ta/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-te/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-tg/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-tgl/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-th/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ti/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-tn/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-tr/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ts/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-tt/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-uk/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ur/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-uz/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ve/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-vi/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-wo/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-xh/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-yue/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-zu/03-dialogs.xml | 2 ++ 93 files changed, 186 insertions(+) diff --git a/AnkiDroid/src/main/res/values-af/03-dialogs.xml b/AnkiDroid/src/main/res/values-af/03-dialogs.xml index 8bcd85da7f0d..b2b824e68d75 100644 --- a/AnkiDroid/src/main/res/values-af/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-af/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-am/03-dialogs.xml b/AnkiDroid/src/main/res/values-am/03-dialogs.xml index af3c6d8eb6de..b7b524ed69cc 100644 --- a/AnkiDroid/src/main/res/values-am/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-am/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ar/03-dialogs.xml b/AnkiDroid/src/main/res/values-ar/03-dialogs.xml index fbb9e47874da..2909d1ad45b4 100644 --- a/AnkiDroid/src/main/res/values-ar/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ar/03-dialogs.xml @@ -289,4 +289,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-az/03-dialogs.xml b/AnkiDroid/src/main/res/values-az/03-dialogs.xml index 1c85e9a659d1..29e60ae44978 100644 --- a/AnkiDroid/src/main/res/values-az/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-az/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-be/03-dialogs.xml b/AnkiDroid/src/main/res/values-be/03-dialogs.xml index 078eed638527..cfdf690b39b4 100644 --- a/AnkiDroid/src/main/res/values-be/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-be/03-dialogs.xml @@ -275,4 +275,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-bg/03-dialogs.xml b/AnkiDroid/src/main/res/values-bg/03-dialogs.xml index 30df386727d0..4e361763e31e 100644 --- a/AnkiDroid/src/main/res/values-bg/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-bg/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-bn/03-dialogs.xml b/AnkiDroid/src/main/res/values-bn/03-dialogs.xml index 912a52288bc5..7b3449e9f842 100644 --- a/AnkiDroid/src/main/res/values-bn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-bn/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ca/03-dialogs.xml b/AnkiDroid/src/main/res/values-ca/03-dialogs.xml index 64b90ff7397c..57a2d7ea4e0f 100644 --- a/AnkiDroid/src/main/res/values-ca/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ca/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml b/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml index 94f9cc8fe29a..ae93ce460ae6 100644 --- a/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-cs/03-dialogs.xml b/AnkiDroid/src/main/res/values-cs/03-dialogs.xml index fe1105ee1aaf..f2c94a3c8a7b 100644 --- a/AnkiDroid/src/main/res/values-cs/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-cs/03-dialogs.xml @@ -273,4 +273,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-da/03-dialogs.xml b/AnkiDroid/src/main/res/values-da/03-dialogs.xml index 9860c38099d6..b2d74ef8f07a 100644 --- a/AnkiDroid/src/main/res/values-da/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-da/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-de/03-dialogs.xml b/AnkiDroid/src/main/res/values-de/03-dialogs.xml index e9c5d13c41ba..e3a2b00d1dc0 100644 --- a/AnkiDroid/src/main/res/values-de/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-de/03-dialogs.xml @@ -255,4 +255,6 @@ Kein Cloze-Notiztyp gefunden. Öffnen Sie den Notiz-Editor oder versuchen Sie es erneut, nachdem Sie einen Cloze-Notiztyp hinzugefügt haben. Offen Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-el/03-dialogs.xml b/AnkiDroid/src/main/res/values-el/03-dialogs.xml index e9391d422e48..95ef4dc72901 100644 --- a/AnkiDroid/src/main/res/values-el/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-el/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-eo/03-dialogs.xml b/AnkiDroid/src/main/res/values-eo/03-dialogs.xml index 8435ddf6b04b..e51af167b9ba 100644 --- a/AnkiDroid/src/main/res/values-eo/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-eo/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml b/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml index 575249c9d4a7..3dfda498bd59 100644 --- a/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml b/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml index 7cf89c9165fe..013d8c572c41 100644 --- a/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-et/03-dialogs.xml b/AnkiDroid/src/main/res/values-et/03-dialogs.xml index e6dbe6ff3344..d5441fb90f66 100644 --- a/AnkiDroid/src/main/res/values-et/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-et/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-eu/03-dialogs.xml b/AnkiDroid/src/main/res/values-eu/03-dialogs.xml index 3ec526b29e0c..4074bacad3ba 100644 --- a/AnkiDroid/src/main/res/values-eu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-eu/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-fa/03-dialogs.xml b/AnkiDroid/src/main/res/values-fa/03-dialogs.xml index 718f1bb46eb4..7eca01b2ef8e 100644 --- a/AnkiDroid/src/main/res/values-fa/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fa/03-dialogs.xml @@ -255,4 +255,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-fi/03-dialogs.xml b/AnkiDroid/src/main/res/values-fi/03-dialogs.xml index fccfb710b9e6..d813e718bf40 100644 --- a/AnkiDroid/src/main/res/values-fi/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fi/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-fil/03-dialogs.xml b/AnkiDroid/src/main/res/values-fil/03-dialogs.xml index 12a9c8bb3d7e..439435e89d51 100644 --- a/AnkiDroid/src/main/res/values-fil/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fil/03-dialogs.xml @@ -258,4 +258,6 @@ Mga file na may di-wastong pag-encode:%d No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-fr/03-dialogs.xml b/AnkiDroid/src/main/res/values-fr/03-dialogs.xml index af4f4e955d7d..163a1d9b7dea 100644 --- a/AnkiDroid/src/main/res/values-fr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fr/03-dialogs.xml @@ -255,4 +255,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-fy/03-dialogs.xml b/AnkiDroid/src/main/res/values-fy/03-dialogs.xml index 3a048687c825..7b9003a709ec 100644 --- a/AnkiDroid/src/main/res/values-fy/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fy/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ga/03-dialogs.xml b/AnkiDroid/src/main/res/values-ga/03-dialogs.xml index 2df5fad0570b..f7ea069f7c5f 100644 --- a/AnkiDroid/src/main/res/values-ga/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ga/03-dialogs.xml @@ -281,4 +281,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-gl/03-dialogs.xml b/AnkiDroid/src/main/res/values-gl/03-dialogs.xml index 8f54d267fe52..e455865fbdaf 100644 --- a/AnkiDroid/src/main/res/values-gl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-gl/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-got/03-dialogs.xml b/AnkiDroid/src/main/res/values-got/03-dialogs.xml index 592c9a81db86..477b4b0b96a7 100644 --- a/AnkiDroid/src/main/res/values-got/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-got/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-gu/03-dialogs.xml b/AnkiDroid/src/main/res/values-gu/03-dialogs.xml index 877ac48e3a1d..7021323e03b4 100644 --- a/AnkiDroid/src/main/res/values-gu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-gu/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-heb/03-dialogs.xml b/AnkiDroid/src/main/res/values-heb/03-dialogs.xml index ae1de9833d98..a58de0ec07df 100644 --- a/AnkiDroid/src/main/res/values-heb/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-heb/03-dialogs.xml @@ -272,4 +272,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-hi/03-dialogs.xml b/AnkiDroid/src/main/res/values-hi/03-dialogs.xml index 3b10cf439538..a81c38c4a680 100644 --- a/AnkiDroid/src/main/res/values-hi/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hi/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-hr/03-dialogs.xml b/AnkiDroid/src/main/res/values-hr/03-dialogs.xml index 18687893667f..f26f1b222fed 100644 --- a/AnkiDroid/src/main/res/values-hr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hr/03-dialogs.xml @@ -265,4 +265,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-hu/03-dialogs.xml b/AnkiDroid/src/main/res/values-hu/03-dialogs.xml index f285107c995b..8a377347a78b 100644 --- a/AnkiDroid/src/main/res/values-hu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hu/03-dialogs.xml @@ -255,4 +255,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-hy/03-dialogs.xml b/AnkiDroid/src/main/res/values-hy/03-dialogs.xml index 7da68d6c3212..63e27d1e396c 100644 --- a/AnkiDroid/src/main/res/values-hy/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hy/03-dialogs.xml @@ -255,4 +255,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ind/03-dialogs.xml b/AnkiDroid/src/main/res/values-ind/03-dialogs.xml index 1123d27f4c85..7aca85bfb3d9 100644 --- a/AnkiDroid/src/main/res/values-ind/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ind/03-dialogs.xml @@ -249,4 +249,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-is/03-dialogs.xml b/AnkiDroid/src/main/res/values-is/03-dialogs.xml index 97b251aaeb27..e98e2bdeae85 100644 --- a/AnkiDroid/src/main/res/values-is/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-is/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-it/03-dialogs.xml b/AnkiDroid/src/main/res/values-it/03-dialogs.xml index 2ff9894b130b..8bb619339b2c 100644 --- a/AnkiDroid/src/main/res/values-it/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-it/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-iw/03-dialogs.xml b/AnkiDroid/src/main/res/values-iw/03-dialogs.xml index ae1de9833d98..a58de0ec07df 100644 --- a/AnkiDroid/src/main/res/values-iw/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-iw/03-dialogs.xml @@ -272,4 +272,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml index 890b90d7ea84..bc0094f50c8f 100644 --- a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml @@ -248,4 +248,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-jv/03-dialogs.xml b/AnkiDroid/src/main/res/values-jv/03-dialogs.xml index 06de335bdd1f..b67423cd4fa6 100644 --- a/AnkiDroid/src/main/res/values-jv/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-jv/03-dialogs.xml @@ -249,4 +249,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ka/03-dialogs.xml b/AnkiDroid/src/main/res/values-ka/03-dialogs.xml index 4ad5b628e6ae..aab7460fd2e8 100644 --- a/AnkiDroid/src/main/res/values-ka/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ka/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-kk/03-dialogs.xml b/AnkiDroid/src/main/res/values-kk/03-dialogs.xml index d47e4a1cccc6..a146fb51e384 100644 --- a/AnkiDroid/src/main/res/values-kk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-kk/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-km/03-dialogs.xml b/AnkiDroid/src/main/res/values-km/03-dialogs.xml index 5a60f84d19a5..a599d07f7667 100644 --- a/AnkiDroid/src/main/res/values-km/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-km/03-dialogs.xml @@ -249,4 +249,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-kn/03-dialogs.xml b/AnkiDroid/src/main/res/values-kn/03-dialogs.xml index 89bf9c84564d..f1620ae643b6 100644 --- a/AnkiDroid/src/main/res/values-kn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-kn/03-dialogs.xml @@ -255,4 +255,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ko/03-dialogs.xml b/AnkiDroid/src/main/res/values-ko/03-dialogs.xml index e2df16252f13..efd95ed93998 100644 --- a/AnkiDroid/src/main/res/values-ko/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ko/03-dialogs.xml @@ -249,4 +249,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ku/03-dialogs.xml b/AnkiDroid/src/main/res/values-ku/03-dialogs.xml index 94f9cc8fe29a..ae93ce460ae6 100644 --- a/AnkiDroid/src/main/res/values-ku/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ku/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ky/03-dialogs.xml b/AnkiDroid/src/main/res/values-ky/03-dialogs.xml index 5f2ddce32012..a1a4978394b3 100644 --- a/AnkiDroid/src/main/res/values-ky/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ky/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-lt/03-dialogs.xml b/AnkiDroid/src/main/res/values-lt/03-dialogs.xml index 59b0a365e4a6..86e01efccd16 100644 --- a/AnkiDroid/src/main/res/values-lt/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-lt/03-dialogs.xml @@ -273,4 +273,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-lv/03-dialogs.xml b/AnkiDroid/src/main/res/values-lv/03-dialogs.xml index a1f57db242f1..761d90e9a6c5 100644 --- a/AnkiDroid/src/main/res/values-lv/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-lv/03-dialogs.xml @@ -265,4 +265,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-mk/03-dialogs.xml b/AnkiDroid/src/main/res/values-mk/03-dialogs.xml index 427b8219533a..0737e2085473 100644 --- a/AnkiDroid/src/main/res/values-mk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mk/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ml/03-dialogs.xml b/AnkiDroid/src/main/res/values-ml/03-dialogs.xml index 3ff88567f68a..aaebaa5c4e8c 100644 --- a/AnkiDroid/src/main/res/values-ml/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ml/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-mn/03-dialogs.xml b/AnkiDroid/src/main/res/values-mn/03-dialogs.xml index ba813c1ca091..11c31e36bb0b 100644 --- a/AnkiDroid/src/main/res/values-mn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mn/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-mr/03-dialogs.xml b/AnkiDroid/src/main/res/values-mr/03-dialogs.xml index 224b229e5c33..e3bf35d3b266 100644 --- a/AnkiDroid/src/main/res/values-mr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mr/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ms/03-dialogs.xml b/AnkiDroid/src/main/res/values-ms/03-dialogs.xml index cb3cbe77c319..824b9ca8795d 100644 --- a/AnkiDroid/src/main/res/values-ms/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ms/03-dialogs.xml @@ -249,4 +249,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-my/03-dialogs.xml b/AnkiDroid/src/main/res/values-my/03-dialogs.xml index d5ea8af44489..8585bbf3b647 100644 --- a/AnkiDroid/src/main/res/values-my/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-my/03-dialogs.xml @@ -249,4 +249,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-nl/03-dialogs.xml b/AnkiDroid/src/main/res/values-nl/03-dialogs.xml index 0ac39909f39e..da8390328d46 100644 --- a/AnkiDroid/src/main/res/values-nl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-nl/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-nn/03-dialogs.xml b/AnkiDroid/src/main/res/values-nn/03-dialogs.xml index c0bdf172618a..33d0dfeebeb2 100644 --- a/AnkiDroid/src/main/res/values-nn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-nn/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-no/03-dialogs.xml b/AnkiDroid/src/main/res/values-no/03-dialogs.xml index 8b8d39cc8d67..d25e908f6f6d 100644 --- a/AnkiDroid/src/main/res/values-no/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-no/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-or/03-dialogs.xml b/AnkiDroid/src/main/res/values-or/03-dialogs.xml index d3700f87ef7c..2bfda8a18a7a 100644 --- a/AnkiDroid/src/main/res/values-or/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-or/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-pa/03-dialogs.xml b/AnkiDroid/src/main/res/values-pa/03-dialogs.xml index 6f53ac8f3795..79fb9f7b89f1 100644 --- a/AnkiDroid/src/main/res/values-pa/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pa/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-pl/03-dialogs.xml b/AnkiDroid/src/main/res/values-pl/03-dialogs.xml index 94ab64ad2362..f3a24c33f117 100644 --- a/AnkiDroid/src/main/res/values-pl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pl/03-dialogs.xml @@ -273,4 +273,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml b/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml index b95b0f7a8dea..9a04574fbc6f 100644 --- a/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml b/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml index 0b5368e28cb7..e6a6fc3795da 100644 --- a/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ro/03-dialogs.xml b/AnkiDroid/src/main/res/values-ro/03-dialogs.xml index 8519fbbf55fa..e2f8090e62bd 100644 --- a/AnkiDroid/src/main/res/values-ro/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ro/03-dialogs.xml @@ -265,4 +265,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ru/03-dialogs.xml b/AnkiDroid/src/main/res/values-ru/03-dialogs.xml index ec47b38fa09c..b2f9e16a9f7a 100644 --- a/AnkiDroid/src/main/res/values-ru/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ru/03-dialogs.xml @@ -274,4 +274,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sat/03-dialogs.xml b/AnkiDroid/src/main/res/values-sat/03-dialogs.xml index 21da876ac53e..e9a005177c1c 100644 --- a/AnkiDroid/src/main/res/values-sat/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sat/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sc/03-dialogs.xml b/AnkiDroid/src/main/res/values-sc/03-dialogs.xml index 534428be80d4..168123039be0 100644 --- a/AnkiDroid/src/main/res/values-sc/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sc/03-dialogs.xml @@ -271,4 +271,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sk/03-dialogs.xml b/AnkiDroid/src/main/res/values-sk/03-dialogs.xml index d95f0fb89431..64ea6276ea3e 100644 --- a/AnkiDroid/src/main/res/values-sk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sk/03-dialogs.xml @@ -271,4 +271,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sl/03-dialogs.xml b/AnkiDroid/src/main/res/values-sl/03-dialogs.xml index 8babbe59a27e..adbd63bd111e 100644 --- a/AnkiDroid/src/main/res/values-sl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sl/03-dialogs.xml @@ -273,4 +273,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sq/03-dialogs.xml b/AnkiDroid/src/main/res/values-sq/03-dialogs.xml index 50399f3f5600..f90ce97a5d58 100644 --- a/AnkiDroid/src/main/res/values-sq/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sq/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sr/03-dialogs.xml b/AnkiDroid/src/main/res/values-sr/03-dialogs.xml index dfb9038009cd..bdbdd5f705e6 100644 --- a/AnkiDroid/src/main/res/values-sr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sr/03-dialogs.xml @@ -265,4 +265,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ss/03-dialogs.xml b/AnkiDroid/src/main/res/values-ss/03-dialogs.xml index ba813c1ca091..11c31e36bb0b 100644 --- a/AnkiDroid/src/main/res/values-ss/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ss/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sv/03-dialogs.xml b/AnkiDroid/src/main/res/values-sv/03-dialogs.xml index c6e71752e0c5..c2d81f146261 100644 --- a/AnkiDroid/src/main/res/values-sv/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sv/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sw/03-dialogs.xml b/AnkiDroid/src/main/res/values-sw/03-dialogs.xml index ba813c1ca091..11c31e36bb0b 100644 --- a/AnkiDroid/src/main/res/values-sw/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sw/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ta/03-dialogs.xml b/AnkiDroid/src/main/res/values-ta/03-dialogs.xml index d27ab99ca902..7bdfb31c044f 100644 --- a/AnkiDroid/src/main/res/values-ta/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ta/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-te/03-dialogs.xml b/AnkiDroid/src/main/res/values-te/03-dialogs.xml index e70b2dd7b156..33e7e2680449 100644 --- a/AnkiDroid/src/main/res/values-te/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-te/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-tg/03-dialogs.xml b/AnkiDroid/src/main/res/values-tg/03-dialogs.xml index 06b2b84615e7..165c214a1f39 100644 --- a/AnkiDroid/src/main/res/values-tg/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tg/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml b/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml index 1d4831513b6a..98ccdc9ad4e4 100644 --- a/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-th/03-dialogs.xml b/AnkiDroid/src/main/res/values-th/03-dialogs.xml index 06de335bdd1f..b67423cd4fa6 100644 --- a/AnkiDroid/src/main/res/values-th/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-th/03-dialogs.xml @@ -249,4 +249,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ti/03-dialogs.xml b/AnkiDroid/src/main/res/values-ti/03-dialogs.xml index ba813c1ca091..11c31e36bb0b 100644 --- a/AnkiDroid/src/main/res/values-ti/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ti/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-tn/03-dialogs.xml b/AnkiDroid/src/main/res/values-tn/03-dialogs.xml index ba813c1ca091..11c31e36bb0b 100644 --- a/AnkiDroid/src/main/res/values-tn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tn/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-tr/03-dialogs.xml b/AnkiDroid/src/main/res/values-tr/03-dialogs.xml index 003035d01884..955b433252ea 100644 --- a/AnkiDroid/src/main/res/values-tr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tr/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ts/03-dialogs.xml b/AnkiDroid/src/main/res/values-ts/03-dialogs.xml index ba813c1ca091..11c31e36bb0b 100644 --- a/AnkiDroid/src/main/res/values-ts/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ts/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-tt/03-dialogs.xml b/AnkiDroid/src/main/res/values-tt/03-dialogs.xml index 9d92aa02a9e0..bae272ca001d 100644 --- a/AnkiDroid/src/main/res/values-tt/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tt/03-dialogs.xml @@ -249,4 +249,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-uk/03-dialogs.xml b/AnkiDroid/src/main/res/values-uk/03-dialogs.xml index 776d01233504..ddc8f9f5c8af 100644 --- a/AnkiDroid/src/main/res/values-uk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-uk/03-dialogs.xml @@ -273,4 +273,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ur/03-dialogs.xml b/AnkiDroid/src/main/res/values-ur/03-dialogs.xml index 9742d98e92f6..45f812782612 100644 --- a/AnkiDroid/src/main/res/values-ur/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ur/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-uz/03-dialogs.xml b/AnkiDroid/src/main/res/values-uz/03-dialogs.xml index 6367030dc171..d574ef8319ca 100644 --- a/AnkiDroid/src/main/res/values-uz/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-uz/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ve/03-dialogs.xml b/AnkiDroid/src/main/res/values-ve/03-dialogs.xml index ba813c1ca091..11c31e36bb0b 100644 --- a/AnkiDroid/src/main/res/values-ve/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ve/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-vi/03-dialogs.xml b/AnkiDroid/src/main/res/values-vi/03-dialogs.xml index 44771d263b80..4190673db9fb 100644 --- a/AnkiDroid/src/main/res/values-vi/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-vi/03-dialogs.xml @@ -249,4 +249,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-wo/03-dialogs.xml b/AnkiDroid/src/main/res/values-wo/03-dialogs.xml index 06de335bdd1f..b67423cd4fa6 100644 --- a/AnkiDroid/src/main/res/values-wo/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-wo/03-dialogs.xml @@ -249,4 +249,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-xh/03-dialogs.xml b/AnkiDroid/src/main/res/values-xh/03-dialogs.xml index ba813c1ca091..11c31e36bb0b 100644 --- a/AnkiDroid/src/main/res/values-xh/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-xh/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-yue/03-dialogs.xml b/AnkiDroid/src/main/res/values-yue/03-dialogs.xml index 1f4c4a5471eb..49d3a7439611 100644 --- a/AnkiDroid/src/main/res/values-yue/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-yue/03-dialogs.xml @@ -249,4 +249,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml index 47aa2f483f2b..326d87788f05 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml @@ -249,4 +249,6 @@ 未找到Cloze类型笔记,打开笔记编辑器或添加Cloze类型笔记后重试。 打开 要关闭,请轻按一次文本 + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml b/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml index c7c17dcd2cb3..2201ecd54893 100644 --- a/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml @@ -249,4 +249,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-zu/03-dialogs.xml b/AnkiDroid/src/main/res/values-zu/03-dialogs.xml index ba813c1ca091..11c31e36bb0b 100644 --- a/AnkiDroid/src/main/res/values-zu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zu/03-dialogs.xml @@ -257,4 +257,6 @@ No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open Single tap text to cloze + + The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d From 2e634d0cc424f9214f5327ff16003e1c3b5222af Mon Sep 17 00:00:00 2001 From: "sargamgayatri0803@gmail.com" Date: Wed, 5 Jun 2024 22:43:06 +0530 Subject: [PATCH 057/138] focus keyboard --- .../src/main/java/com/ichi2/anki/notetype/AddNewNotesType.kt | 4 ++++ .../src/main/java/com/ichi2/anki/notetype/ManageNotetypes.kt | 1 + 2 files changed, 5 insertions(+) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/notetype/AddNewNotesType.kt b/AnkiDroid/src/main/java/com/ichi2/anki/notetype/AddNewNotesType.kt index 37c5fe9e1831..d4bad50165f9 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/notetype/AddNewNotesType.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/notetype/AddNewNotesType.kt @@ -17,6 +17,7 @@ package com.ichi2.anki.notetype import android.view.LayoutInflater import android.view.View +import android.view.WindowManager import android.widget.AdapterView import android.widget.ArrayAdapter import android.widget.EditText @@ -98,6 +99,7 @@ class AddNewNotesType(private val activity: ManageNotetypes) { override fun onItemSelected(av: AdapterView<*>?, rv: View?, index: Int, id: Long) { val selectedNotetype = optionsToDisplay[index] nameInput.setText(randomizeName(selectedNotetype.name)) + nameInput.setSelection(nameInput.text.length) } override fun onNothingSelected(widget: AdapterView<*>?) { @@ -117,6 +119,8 @@ class AddNewNotesType(private val activity: ManageNotetypes) { ).apply { setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) } + nameInput.requestFocus() + window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE) } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/notetype/ManageNotetypes.kt b/AnkiDroid/src/main/java/com/ichi2/anki/notetype/ManageNotetypes.kt index 5f867c33b874..4e0dceddeb19 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/notetype/ManageNotetypes.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/notetype/ManageNotetypes.kt @@ -139,6 +139,7 @@ class ManageNotetypes : AnkiActivity() { }.input( prefill = noteTypeUiModel.name, waitForPositiveButton = false, + displayKeyboard = true, callback = { dialog, text -> dialog.positiveButton.isEnabled = text.isNotEmpty() && !allNotetypes.map { it.name } From e14aec6eec029ed0af634e2f785914f1269f4d18 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Thu, 6 Jun 2024 08:42:48 +0100 Subject: [PATCH 058/138] docs: ChangeManager.Subscriber - lambdas Documented that lambdas should not be used Issue 16541 --- AnkiDroid/src/main/java/com/ichi2/libanki/ChangeManager.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/ChangeManager.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/ChangeManager.kt index 9b2dc455e05d..d793487aa62d 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/ChangeManager.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/ChangeManager.kt @@ -44,7 +44,9 @@ import java.lang.ref.WeakReference import java.util.concurrent.CopyOnWriteArrayList object ChangeManager { - fun interface Subscriber { + // do not make this a 'fun interface' - lambdas may immediately be GCed + // due to the use of WeakReference + interface Subscriber { /** * Called after a backend method invoked via col.op() or col.opWithProgress() * has modified the collection. Subscriber should inspect the changes, and update From 20add73857261a1562b5ce793d9ec0b86b2d92d2 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Thu, 6 Jun 2024 14:12:35 +0100 Subject: [PATCH 059/138] refactor(card-browser): updateSelectedCardsFlag (#16547) * refactor(card-browser): Card param -> CardId We're going to refactor `updateSelectedCardsFlag` to return cids and these were all that is required * refactor(card-browser): remove unused method * searchWithFilterQuery * refactor(card-browser-view-model): update flags * onEach { load() } called collection.load * broken in 0d69cacde9886feba40b98e19f851e62d5a29fcd --- .../main/java/com/ichi2/anki/CardBrowser.kt | 39 ++++++------------- .../anki/browser/CardBrowserViewModel.kt | 10 ++--- .../src/main/java/com/ichi2/libanki/Card.kt | 2 +- 3 files changed, 15 insertions(+), 36 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt index 75191406ad11..167f58ab92ec 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt @@ -172,7 +172,7 @@ open class CardBrowser : } if (result.resultCode != RESULT_CANCELED) { Timber.i("CardBrowser:: CardBrowser: Saving card...") - launchCatchingTask { saveEditedCard() } + saveEditedCard() } val data = result.data if (data != null && @@ -483,10 +483,6 @@ open class CardBrowser : viewModel.flowOfInitCompleted.launchCollectionInLifecycleScope(::initCompletedChanged) } - fun searchWithFilterQuery(filterQuery: String) = launchCatchingTask { - viewModel.setFilterQuery(filterQuery) - } - // Finish initializing the activity after the collection has been correctly loaded override fun onCollectionLoaded(col: Collection) { super.onCollectionLoaded(col) @@ -907,12 +903,12 @@ open class CardBrowser : @VisibleForTesting suspend fun updateSelectedCardsFlag(flag: Flag) { // list of cards with updated flags - val updatedCards = withProgress { viewModel.updateSelectedCardsFlag(flag) } + val updatedCardIds = withProgress { viewModel.updateSelectedCardsFlag(flag) } // TODO: try to offload the cards processing in updateCardsInList() on a background thread, // otherwise it could hang the main thread - updateCardsInList(updatedCards) + updateCardsInList(updatedCardIds) invalidateOptionsMenu() // maybe the availability of undo changed - if (updatedCards.any { card -> card.id == reviewerCardId }) { + if (updatedCardIds.any { it == reviewerCardId }) { reloadRequired = true } } @@ -1422,13 +1418,6 @@ open class CardBrowser : return resources.getQuantityString(subtitleId, count, count) } - // convenience method for updateCardsInList(...) - private fun updateCardInList(card: Card) { - val cards: MutableList = ArrayList(1) - cards.add(card) - updateCardsInList(cards) - } - /** Returns the decks which are valid targets for "Change Deck" */ suspend fun getValidDecksForChangeDeck(): List = deckSpinnerSelection.computeDropDownDecks(includeFiltered = false) @@ -1474,29 +1463,23 @@ open class CardBrowser : fun filterByFlag(flag: Flag) = launchCatchingTask { viewModel.setFlagFilter(flag) } /** - * Loads/Reloads (Updates the Q, A & etc) of cards in the [cards] list - * @param cards Cards that were changed + * Loads/Reloads (Updates the Q, A & etc) of cards in the [cardIds] list + * @param cardIds Card IDs that were changed */ - private fun updateCardsInList(cards: List) { + private fun updateCardsInList(cardIds: List) { val idToPos = viewModel.cardIdToPositionMap // TODO: Inefficient - cards - .mapNotNull { c -> idToPos[c.id] } + cardIds + .mapNotNull { cid -> idToPos[cid] } .filterNot { pos -> pos >= viewModel.rowCount } .map { pos -> viewModel.getRowAtPosition(pos) } .forEach { it.load(true, viewModel.column1Index, viewModel.column2Index) } updateList() } - private suspend fun saveEditedCard() { + private fun saveEditedCard() { Timber.d("CardBrowser - saveEditedCard()") - val card = try { - withCol { getCard(currentCardId) } - } catch (e: Exception) { - Timber.i("edited card no longer exists") - return - } - updateCardInList(card) + updateCardsInList(listOf(currentCardId)) } /** diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index 5b52bd2f55bc..863e0d652e3d 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -691,14 +691,10 @@ class CardBrowserViewModel( } } - suspend fun updateSelectedCardsFlag(flag: Flag): List { + suspend fun updateSelectedCardsFlag(flag: Flag): List { val idsToChange = queryAllSelectedCardIds() - return withCol { - setUserFlag(flag, cids = idsToChange) - selectedRowIds - .map { getCard(it) } - .onEach { load() } - } + withCol { setUserFlag(flag, cids = idsToChange) } + return idsToChange } /** diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/Card.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/Card.kt index 46edaa4cdf15..3a1d79107b7f 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/Card.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/Card.kt @@ -68,7 +68,7 @@ open class Card : Cloneable { private var elapsedTime: Long = 0 @set:VisibleForTesting - var id: Long = 0 + var id: CardId = 0 var nid: NoteId = 0 var did: DeckId = 0 var ord = 0 From eed9ca8b4d93d5371a985186e7abfffa5cdb75cc Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Wed, 29 May 2024 14:42:43 +0100 Subject: [PATCH 060/138] build: create 'common' module * Defined as 'Android Library' * Replaced junit reference with vintage engine * to match project * Removed example unit tests --- AnkiDroid/build.gradle | 3 ++ common/.gitignore | 1 + common/README.md | 66 +++++++++++++++++++++++++++++ common/build.gradle.kts | 47 ++++++++++++++++++++ common/consumer-rules.pro | 0 common/proguard-rules.pro | 21 +++++++++ common/src/main/AndroidManifest.xml | 4 ++ settings.gradle.kts | 2 +- 8 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 common/.gitignore create mode 100644 common/README.md create mode 100644 common/build.gradle.kts create mode 100644 common/consumer-rules.pro create mode 100644 common/proguard-rules.pro create mode 100644 common/src/main/AndroidManifest.xml diff --git a/AnkiDroid/build.gradle b/AnkiDroid/build.gradle index 3d27a9144c06..8a4a04fd5ea8 100644 --- a/AnkiDroid/build.gradle +++ b/AnkiDroid/build.gradle @@ -306,6 +306,9 @@ dependencies { compileOnly libs.auto.service.annotations annotationProcessor libs.auto.service + // modules + implementation project(":common") + implementation libs.androidx.activity implementation libs.androidx.annotation implementation libs.androidx.appcompat diff --git a/common/.gitignore b/common/.gitignore new file mode 100644 index 000000000000..42afabfd2abe --- /dev/null +++ b/common/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/common/README.md b/common/README.md new file mode 100644 index 000000000000..ac91f9aa3251 --- /dev/null +++ b/common/README.md @@ -0,0 +1,66 @@ +## AnkiDroid Common + +AnkiDroid Common is a [Gradle module](https://developer.android.com/topic/modularization) +containing utility functions, and definitions for core functionality used by other modules +within AnkiDroid. Common should be the base of the AnkiDroid dependency tree. + +Common is used by `libAnki` (which has no Android dependencies), so dependencies on the Android +framework should be in packages named `android`. + +This module is expected to define interfaces which are initialized in the `AnkiDroid` module + +## Packages + +### `com.ichi2.anki.common` + +Definitions/interfaces exposing core functionality e.g. `CrashReportService`, `UsageAnalytics` + +These are to be initialized higher up the dependency tree, typically in `AnkiDroid` + +### `com.ichi2.anki.common.utils` + +Utility classes and methods without an Android dependency + + +### `com.ichi2.anki.common.utils.ext` + +Extension methods, universally applicable to the classes they extend + +Examples: + +* `Int.kt` - `ifNotZero` +* `InputStream.kt` - `convertToString` + +### `com.ichi2.anki.common.utils.android` + +Utilities with a dependency on Android + +## Context + +This is a work in progress. As discussed in +[#12582](https://github.com/ankidroid/Anki-Android/issues/12582), AnkiDroid decided to split the +codebase into two modules, `libAnki` (business logic) and `AnkiDroid` (code interacting with +Android APIs). + +At the time of writing, this split is not yet done. We expect to do it with the following steps: + +* `com.ichi2.compat` was deemed to be an easy module to split out to trial this refactor + but this had circular dependencies +* A `common` module was proposed to fix this +* To reduce the execution time of tests, `libAnki` should have no dependencies on Android + * A lint rule will be applied to `libAnki` from using Android dependencies + * The alternate: splitting modules based on architecture was deemed to be unwieldy + +The following were blockers for `compat` to be split out + +* `isRobolectric` +* `CrashReportService` +* `showThemedToast` +* `TimeManager` (maybe) +* `@KotlinCleanup` (maybe) + +Discussed on Discord: https://discord.gg/qjzcRTx + +* Discussion: https://discord.com/channels/368267295601983490/701922522836369498/1243991110888591482 +* Thread: https://discord.com/channels/368267295601983490/1244372448233914438 +* https://github.com/ankidroid/Anki-Android/pull/16498 diff --git a/common/build.gradle.kts b/common/build.gradle.kts new file mode 100644 index 000000000000..1e325093014e --- /dev/null +++ b/common/build.gradle.kts @@ -0,0 +1,47 @@ +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) +} + +android { + // this cannot conflict with com.ichi2.anki + // but we can define files in 'com.ichi2.anki' inside 'common' + // even with this namespace + namespace = "com.ichi2.anki.common" + compileSdk = 34 + + defaultConfig { + minSdk = 23 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } +} + +dependencies { + + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.appcompat) + implementation(libs.google.material) + testImplementation(libs.junit.jupiter) + testImplementation(libs.junit.vintage.engine) + androidTestImplementation(libs.androidx.test.junit) + androidTestImplementation(libs.androidx.espresso.core) +} diff --git a/common/consumer-rules.pro b/common/consumer-rules.pro new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/common/proguard-rules.pro b/common/proguard-rules.pro new file mode 100644 index 000000000000..481bb4348141 --- /dev/null +++ b/common/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/common/src/main/AndroidManifest.xml b/common/src/main/AndroidManifest.xml new file mode 100644 index 000000000000..44008a4332e6 --- /dev/null +++ b/common/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index e9a4909ec790..082d401dba48 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -26,4 +26,4 @@ dependencyResolutionManagement { } } -include(":lint-rules", ":api", ":AnkiDroid", ":testlib") \ No newline at end of file +include(":lint-rules", ":api", ":AnkiDroid", ":testlib", ":common") \ No newline at end of file From a8b22f6dd3a4b8db508a2ae3cf440fe32d946b21 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Wed, 29 May 2024 15:12:33 +0100 Subject: [PATCH 061/138] build: extract 'TestUtils' to 'common' module A number of circular dependencies on 'compat' meant that all functionality could not be extracted from 'AdaptionUtil' * We need to extract 'isRobolectric' * isRunningAsUnitTest is an easy extraction * added in 7ada532c5cfb72626ec2c5ef348b7570de62453a --- .../main/java/com/ichi2/anki/AnkiDroidApp.kt | 3 +- .../main/java/com/ichi2/anki/CardBrowser.kt | 1 + .../java/com/ichi2/anki/CollectionManager.kt | 3 +- .../java/com/ichi2/anki/logging/LogType.kt | 2 +- .../main/java/com/ichi2/compat/CompatV24.kt | 2 +- .../main/java/com/ichi2/utils/AdaptionUtil.kt | 21 +----------- .../main/java/com/ichi2/utils/Permissions.kt | 2 +- .../java/com/ichi2/anki/CardBrowserTest.kt | 13 +++++--- common/build.gradle.kts | 1 + .../com/ichi2/anki/common/utils/TestUtils.kt | 33 +++++++++++++++++++ .../anki/common/utils/android/TestUtils.kt | 21 ++++++++++++ 11 files changed, 71 insertions(+), 31 deletions(-) create mode 100644 common/src/main/java/com/ichi2/anki/common/utils/TestUtils.kt create mode 100644 common/src/main/java/com/ichi2/anki/common/utils/android/TestUtils.kt diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidApp.kt b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidApp.kt index cbe481c3cc1f..b81f0559983f 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidApp.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidApp.kt @@ -37,6 +37,7 @@ import androidx.work.Configuration import com.ichi2.anki.CrashReportService.sendExceptionReport import com.ichi2.anki.analytics.UsageAnalytics import com.ichi2.anki.browser.SharedPreferencesLastDeckIdRepository +import com.ichi2.anki.common.utils.isRunningAsUnitTest import com.ichi2.anki.contextmenu.AnkiCardContextMenu import com.ichi2.anki.contextmenu.CardBrowserContextMenu import com.ichi2.anki.exception.StorageAccessException @@ -152,7 +153,7 @@ open class AnkiDroidApp : Application(), Configuration.Provider { } // make default HTML / JS debugging true for debug build and disable for unit/android tests - if (BuildConfig.DEBUG && !AdaptionUtil.isRunningAsUnitTest) { + if (BuildConfig.DEBUG && !isRunningAsUnitTest) { preferences.edit { putBoolean("html_javascript_debugging", true) } } CardBrowserContextMenu.ensureConsistentStateWithPreferenceStatus( diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt index 167f58ab92ec..b424e4b32288 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt @@ -51,6 +51,7 @@ import com.ichi2.anki.browser.PreviewerIdsFile import com.ichi2.anki.browser.SaveSearchResult import com.ichi2.anki.browser.SharedPreferencesLastDeckIdRepository import com.ichi2.anki.browser.toCardBrowserLaunchOptions +import com.ichi2.anki.common.utils.android.isRobolectric import com.ichi2.anki.dialogs.* import com.ichi2.anki.dialogs.CardBrowserMySearchesDialog.Companion.newInstance import com.ichi2.anki.dialogs.CardBrowserMySearchesDialog.MySearchesDialogListener diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CollectionManager.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CollectionManager.kt index 7b8051c0851a..2632827a9e0d 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CollectionManager.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CollectionManager.kt @@ -21,13 +21,13 @@ import android.content.Context import androidx.annotation.VisibleForTesting import androidx.annotation.WorkerThread import anki.backend.backendError +import com.ichi2.anki.common.utils.android.isRobolectric import com.ichi2.anki.servicelayer.ValidatedMigrationSourceAndDestination import com.ichi2.anki.servicelayer.scopedstorage.MigrateEssentialFiles import com.ichi2.libanki.Collection import com.ichi2.libanki.Storage.collection import com.ichi2.libanki.importCollectionPackage import com.ichi2.utils.Threads -import com.ichi2.utils.isRobolectric import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking @@ -40,7 +40,6 @@ import okio.withLock import timber.log.Timber import java.io.File import java.util.concurrent.locks.ReentrantLock -import kotlin.concurrent.withLock object CollectionManager { /** diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/logging/LogType.kt b/AnkiDroid/src/main/java/com/ichi2/anki/logging/LogType.kt index 1f89426ec06b..c713ea5f49cf 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/logging/LogType.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/logging/LogType.kt @@ -17,7 +17,7 @@ package com.ichi2.anki.logging import com.ichi2.anki.BuildConfig -import com.ichi2.utils.isRobolectric +import com.ichi2.anki.common.utils.android.isRobolectric import timber.log.Timber enum class LogType { diff --git a/AnkiDroid/src/main/java/com/ichi2/compat/CompatV24.kt b/AnkiDroid/src/main/java/com/ichi2/compat/CompatV24.kt index 8ddae07042e6..1ee05b2cc627 100644 --- a/AnkiDroid/src/main/java/com/ichi2/compat/CompatV24.kt +++ b/AnkiDroid/src/main/java/com/ichi2/compat/CompatV24.kt @@ -19,7 +19,7 @@ package com.ichi2.compat import android.annotation.TargetApi import android.icu.util.ULocale import android.view.MotionEvent -import com.ichi2.utils.isRobolectric +import com.ichi2.anki.common.utils.android.isRobolectric import timber.log.Timber import java.util.Locale diff --git a/AnkiDroid/src/main/java/com/ichi2/utils/AdaptionUtil.kt b/AnkiDroid/src/main/java/com/ichi2/utils/AdaptionUtil.kt index 8097f23a85b4..c9534fa84422 100644 --- a/AnkiDroid/src/main/java/com/ichi2/utils/AdaptionUtil.kt +++ b/AnkiDroid/src/main/java/com/ichi2/utils/AdaptionUtil.kt @@ -31,7 +31,7 @@ import com.ichi2.compat.CompatHelper.Companion.queryIntentActivitiesCompat import com.ichi2.compat.PackageInfoFlagsCompat import com.ichi2.compat.ResolveInfoFlagsCompat import timber.log.Timber -import java.util.* +import java.util.Locale object AdaptionUtil { private var sHasRunWebBrowserCheck = false @@ -130,23 +130,4 @@ object AdaptionUtil { val manufacturer = Build.MANUFACTURER ?: return false return manufacturer.lowercase(Locale.ROOT) == "vivo" } - - /** make default HTML / JS debugging true for debug build and disable for unit/android tests - * isRunningAsUnitTest checks if we are in debug or testing environment by checking if org.junit.Test class - * is imported. - * https://stackoverflow.com/questions/28550370/how-to-detect-whether-android-app-is-running-ui-test-with-espresso - */ - val isRunningAsUnitTest: Boolean - get() { - try { - Class.forName("org.junit.Test") - } catch (ignored: ClassNotFoundException) { - Timber.d("isRunningAsUnitTest: %b", false) - return false - } - Timber.d("isRunningAsUnitTest: %b", true) - return true - } } - -val isRobolectric get() = Build.FINGERPRINT?.startsWith("robolectric") ?: false diff --git a/AnkiDroid/src/main/java/com/ichi2/utils/Permissions.kt b/AnkiDroid/src/main/java/com/ichi2/utils/Permissions.kt index 9cea7c0a9d5e..8f4b8594c347 100644 --- a/AnkiDroid/src/main/java/com/ichi2/utils/Permissions.kt +++ b/AnkiDroid/src/main/java/com/ichi2/utils/Permissions.kt @@ -26,10 +26,10 @@ import androidx.annotation.RequiresApi import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment +import com.ichi2.anki.common.utils.android.isRobolectric import com.ichi2.compat.CompatHelper.Companion.getPackageInfoCompat import com.ichi2.compat.PackageInfoFlagsCompat import timber.log.Timber -import java.lang.Exception object Permissions { const val MANAGE_EXTERNAL_STORAGE = "android.permission.MANAGE_EXTERNAL_STORAGE" diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt index 6af55c4be8af..740a186f530c 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt @@ -34,8 +34,10 @@ import com.ichi2.anki.browser.CardBrowserColumn import com.ichi2.anki.browser.CardBrowserViewModel import com.ichi2.anki.browser.CardBrowserViewModel.Companion.DISPLAY_COLUMN_1_KEY import com.ichi2.anki.browser.CardBrowserViewModel.Companion.DISPLAY_COLUMN_2_KEY +import com.ichi2.anki.common.utils.isRunningAsUnitTest import com.ichi2.anki.dialogs.DeckSelectionDialog -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.scheduling.ForgetCardsViewModel import com.ichi2.anki.servicelayer.NoteService @@ -53,11 +55,12 @@ import com.ichi2.testutils.OS import com.ichi2.testutils.TestClass import com.ichi2.testutils.getSharedPrefs import com.ichi2.ui.FixedTextView -import com.ichi2.utils.AdaptionUtil import com.ichi2.utils.LanguageUtil import io.mockk.every import io.mockk.mockkObject +import io.mockk.mockkStatic import io.mockk.unmockkObject +import io.mockk.unmockkStatic import kotlinx.coroutines.runBlocking import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.equalTo @@ -396,11 +399,11 @@ class CardBrowserTest : RobolectricTest() { @Test fun startupFromCardBrowserActionItemShouldEndActivityIfNoPermissions() { try { - mockkObject(AdaptionUtil) + mockkStatic(::isRunningAsUnitTest) mockkObject(IntentHandler) every { grantedStoragePermissions(any(), any()) } returns false - every { AdaptionUtil.isRunningAsUnitTest } returns false + every { isRunningAsUnitTest } returns false val browserController = Robolectric.buildActivity(CardBrowser::class.java).create() val cardBrowser = browserController.get() @@ -408,7 +411,7 @@ class CardBrowserTest : RobolectricTest() { assertThat("Activity should be finishing", cardBrowser.isFinishing) } finally { - unmockkObject(AdaptionUtil) + unmockkStatic(::isRunningAsUnitTest) unmockkObject(IntentHandler) } } diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 1e325093014e..f17ac924a2d3 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -40,6 +40,7 @@ dependencies { implementation(libs.androidx.core.ktx) implementation(libs.androidx.appcompat) implementation(libs.google.material) + implementation(libs.jakewharton.timber) testImplementation(libs.junit.jupiter) testImplementation(libs.junit.vintage.engine) androidTestImplementation(libs.androidx.test.junit) diff --git a/common/src/main/java/com/ichi2/anki/common/utils/TestUtils.kt b/common/src/main/java/com/ichi2/anki/common/utils/TestUtils.kt new file mode 100644 index 000000000000..7204983b2502 --- /dev/null +++ b/common/src/main/java/com/ichi2/anki/common/utils/TestUtils.kt @@ -0,0 +1,33 @@ +/* + * 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 . + */ +package com.ichi2.anki.common.utils + +import timber.log.Timber + +/** make default HTML / JS debugging true for debug build and disable for unit/android tests + * isRunningAsUnitTest checks if we are in debug or testing environment by checking if org.junit.Test class + * is imported. + * https://stackoverflow.com/questions/28550370/how-to-detect-whether-android-app-is-running-ui-test-with-espresso + */ +val isRunningAsUnitTest: Boolean + get() { + try { + Class.forName("org.junit.Test") + } catch (ignored: ClassNotFoundException) { + Timber.d("isRunningAsUnitTest: %b", false) + return false + } + Timber.d("isRunningAsUnitTest: %b", true) + return true + } diff --git a/common/src/main/java/com/ichi2/anki/common/utils/android/TestUtils.kt b/common/src/main/java/com/ichi2/anki/common/utils/android/TestUtils.kt new file mode 100644 index 000000000000..58c2ea4d024b --- /dev/null +++ b/common/src/main/java/com/ichi2/anki/common/utils/android/TestUtils.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 David Allison + * + * 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 . + */ + +package com.ichi2.anki.common.utils.android + +import android.os.Build + +val isRobolectric get() = Build.FINGERPRINT?.startsWith("robolectric") ?: false From 79286aaad3e352671dc29d489b202c08defb10e0 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Sat, 8 Jun 2024 19:26:30 +0100 Subject: [PATCH 062/138] lint(collection): make non-open Fixes a few warnings --- AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt index 79a4d86e126b..de7dd4e56dae 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt @@ -57,7 +57,7 @@ import java.util.* // This module manages the tag cache and tags for notes. @KotlinCleanup("inline function in init { } so we don't need to init `crt` etc... at the definition") @WorkerThread -open class Collection( +class Collection( /** * The path to the collection.anki2 database. Must be unicode and openable with [File]. */ @@ -227,7 +227,7 @@ open class Collection( * is used so that the type does not states that an exception is * thrown when in fact it is never thrown. */ - open fun modSchemaNoCheck() { + fun modSchemaNoCheck() { db.execute( "update col set scm=?, mod=?", TimeManager.time.intTimeMS(), From f99a288bf46d1b6a444a4dd99db49ff634b912b0 Mon Sep 17 00:00:00 2001 From: Robozinho <65715921+robozinhod@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:49:08 -0300 Subject: [PATCH 063/138] fix navbar color in reviewer --- AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt b/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt index 8719b2e979c3..c678209e1078 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt @@ -67,6 +67,7 @@ import com.ichi2.anki.servicelayer.NoteService.isMarked import com.ichi2.anki.servicelayer.NoteService.toggleMark import com.ichi2.anki.snackbar.showSnackbar import com.ichi2.anki.ui.internationalization.toSentenceCase +import com.ichi2.anki.utils.navBarNeedsScrim import com.ichi2.anki.utils.remainingTime import com.ichi2.annotations.NeedsTest import com.ichi2.audio.AudioRecordingController @@ -187,7 +188,7 @@ open class Reviewer : textBarReview = findViewById(R.id.review_number) toolbar = findViewById(R.id.toolbar) micToolBarLayer = findViewById(R.id.mic_tool_bar_layer) - if (sharedPrefs().getString("answerButtonPosition", "bottom") == "bottom") { + if (sharedPrefs().getString("answerButtonPosition", "bottom") == "bottom" && !navBarNeedsScrim) { setNavigationBarColor(R.attr.showAnswerColor) } if (!sharedPrefs().getBoolean("showDeckTitle", false)) { From 41eea1e220e9b78cc6346d3de743191eea7f6898 Mon Sep 17 00:00:00 2001 From: AnkiDroid Translations Date: Sun, 9 Jun 2024 14:19:00 +0000 Subject: [PATCH 064/138] Updated strings from Crowdin --- AnkiDroid/src/main/res/values-de/03-dialogs.xml | 2 +- AnkiDroid/src/main/res/values-fil/02-strings.xml | 6 +++--- AnkiDroid/src/main/res/values-fil/03-dialogs.xml | 2 +- AnkiDroid/src/main/res/values-ja/01-core.xml | 2 +- AnkiDroid/src/main/res/values-ja/03-dialogs.xml | 10 +++++----- AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/AnkiDroid/src/main/res/values-de/03-dialogs.xml b/AnkiDroid/src/main/res/values-de/03-dialogs.xml index e3a2b00d1dc0..c67aa0a1479e 100644 --- a/AnkiDroid/src/main/res/values-de/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-de/03-dialogs.xml @@ -256,5 +256,5 @@ Offen Single tap text to cloze - The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + Das System-WebView ist veraltet. Einige Funktionen werden nicht korrekt funktionieren. Bitte aktualisieren Sie es.\n\nInstallierte Version: %1$d\nMindestanforderung: %2$d diff --git a/AnkiDroid/src/main/res/values-fil/02-strings.xml b/AnkiDroid/src/main/res/values-fil/02-strings.xml index 602199cc1f3f..6588c9aa89e7 100644 --- a/AnkiDroid/src/main/res/values-fil/02-strings.xml +++ b/AnkiDroid/src/main/res/values-fil/02-strings.xml @@ -144,9 +144,9 @@ Kopyahin bilang Markdown %1$d sa %2$d Baguhin ang pangalan - Tsek - I-tsek ang database - I-tsek ang media + Suriin + Suriin ang database + Suriin ang media Mga walang lamang card Walang laman ang card na ito. Gamitin ang opsiyon na \"Mga walang lamang card\" mula sa menu sa screen ng listahan ng deck. I-type ang sagot: hindi kilalang patlang %s diff --git a/AnkiDroid/src/main/res/values-fil/03-dialogs.xml b/AnkiDroid/src/main/res/values-fil/03-dialogs.xml index 439435e89d51..2b9c12267f39 100644 --- a/AnkiDroid/src/main/res/values-fil/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fil/03-dialogs.xml @@ -109,7 +109,7 @@ Palitan Ang path na tinukoy ay hindi isang wastong direktoryo - I - tsek ang media? + Suriin ang media? Ito ay maaaring tumagal ng mahabang oras kasama ang malalaking koleksyon ng media Sinusuri ang media… Ang media ay sinuri diff --git a/AnkiDroid/src/main/res/values-ja/01-core.xml b/AnkiDroid/src/main/res/values-ja/01-core.xml index f0c56f65a7c6..6769342e7f86 100644 --- a/AnkiDroid/src/main/res/values-ja/01-core.xml +++ b/AnkiDroid/src/main/res/values-ja/01-core.xml @@ -241,5 +241,5 @@ 画像穴埋め問題 アカウントを削除 - Instant card + 穴埋めクイック作成 diff --git a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml index bc0094f50c8f..fa7816cdcb8b 100644 --- a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml @@ -244,10 +244,10 @@ 最短 最長 - Cloze Type Note Required - No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. - Open - Single tap text to cloze + 「穴埋め問題」用のノートタイプが必要です + 「穴埋め問題」に対応したノートタイプが見つかりませんでした。アプリで「穴埋め問題」に対応したノートタイプを追加してからもう一度試すか、それ以外のノートタイプのノートを編集するため、「開く」ボタンを押してください。 + 開く + シングルタップで穴埋め問題 - The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + 「AndroidシステムのWebView 」(または「Android System WebView」)が古くなっています。いくつかの機能が正しく動作しません。更新してください。\n\nインストールされているバージョン: %1$d\n最低限必要なバージョン: %2$d diff --git a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml index 326d87788f05..add3abff547e 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml @@ -250,5 +250,5 @@ 打开 要关闭,请轻按一次文本 - The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + 系统 WebView 已过时。有些功能将无法正常工作。请更新它。\n\n已安装版本: %1$d\n所需最低版本: %2$d From 47ca03d1d4907dfcc6ea178cb131c340a5fced6d Mon Sep 17 00:00:00 2001 From: Robozinho <65715921+robozinhod@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:31:48 -0300 Subject: [PATCH 065/138] improve media sync message --- AnkiDroid/src/main/java/com/ichi2/anki/Sync.kt | 3 ++- AnkiDroid/src/main/res/values/04-network.xml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Sync.kt b/AnkiDroid/src/main/java/com/ichi2/anki/Sync.kt index dda0027c33b6..1e74bb490114 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/Sync.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/Sync.kt @@ -238,7 +238,8 @@ private suspend fun handleNormalSync( SyncCollectionResponse.ChangesRequired.NO_CHANGES -> { // scheduler version may have changed withCol { _loadScheduler() } - deckPicker.showSyncLogMessage(R.string.sync_database_acknowledge, output.serverMessage) + val message = if (syncMedia) R.string.col_synced_media_in_background else R.string.sync_database_acknowledge + deckPicker.showSyncLogMessage(message, output.serverMessage) deckPicker.refreshState() if (syncMedia) { SyncMediaWorker.start(deckPicker, auth2) diff --git a/AnkiDroid/src/main/res/values/04-network.xml b/AnkiDroid/src/main/res/values/04-network.xml index 6b27dfc22ae7..6d02e38f3e7a 100644 --- a/AnkiDroid/src/main/res/values/04-network.xml +++ b/AnkiDroid/src/main/res/values/04-network.xml @@ -48,6 +48,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local From ba4808c1cfa413d975d6a2a4fccf7025130a798e Mon Sep 17 00:00:00 2001 From: AnkiDroid Translations Date: Sun, 9 Jun 2024 18:19:25 +0000 Subject: [PATCH 066/138] Updated strings from Crowdin --- AnkiDroid/src/main/res/values-af/04-network.xml | 1 + AnkiDroid/src/main/res/values-am/04-network.xml | 1 + AnkiDroid/src/main/res/values-ar/04-network.xml | 1 + AnkiDroid/src/main/res/values-az/04-network.xml | 1 + AnkiDroid/src/main/res/values-be/04-network.xml | 1 + AnkiDroid/src/main/res/values-bg/04-network.xml | 1 + AnkiDroid/src/main/res/values-bn/04-network.xml | 1 + AnkiDroid/src/main/res/values-ca/04-network.xml | 1 + AnkiDroid/src/main/res/values-ckb/04-network.xml | 1 + AnkiDroid/src/main/res/values-cs/04-network.xml | 1 + AnkiDroid/src/main/res/values-da/04-network.xml | 1 + AnkiDroid/src/main/res/values-de/04-network.xml | 1 + AnkiDroid/src/main/res/values-el/04-network.xml | 1 + AnkiDroid/src/main/res/values-eo/04-network.xml | 1 + AnkiDroid/src/main/res/values-es-rAR/04-network.xml | 1 + AnkiDroid/src/main/res/values-es-rES/04-network.xml | 1 + AnkiDroid/src/main/res/values-et/04-network.xml | 1 + AnkiDroid/src/main/res/values-eu/04-network.xml | 1 + AnkiDroid/src/main/res/values-fa/04-network.xml | 1 + AnkiDroid/src/main/res/values-fi/04-network.xml | 1 + AnkiDroid/src/main/res/values-fil/04-network.xml | 1 + AnkiDroid/src/main/res/values-fr/04-network.xml | 1 + AnkiDroid/src/main/res/values-fy/04-network.xml | 1 + AnkiDroid/src/main/res/values-ga/04-network.xml | 1 + AnkiDroid/src/main/res/values-gl/04-network.xml | 1 + AnkiDroid/src/main/res/values-got/04-network.xml | 1 + AnkiDroid/src/main/res/values-gu/04-network.xml | 1 + AnkiDroid/src/main/res/values-heb/04-network.xml | 1 + AnkiDroid/src/main/res/values-hi/04-network.xml | 1 + AnkiDroid/src/main/res/values-hr/04-network.xml | 1 + AnkiDroid/src/main/res/values-hu/04-network.xml | 1 + AnkiDroid/src/main/res/values-hy/04-network.xml | 1 + AnkiDroid/src/main/res/values-ind/04-network.xml | 1 + AnkiDroid/src/main/res/values-is/04-network.xml | 1 + AnkiDroid/src/main/res/values-it/04-network.xml | 1 + AnkiDroid/src/main/res/values-iw/04-network.xml | 1 + AnkiDroid/src/main/res/values-ja/04-network.xml | 1 + AnkiDroid/src/main/res/values-jv/04-network.xml | 1 + AnkiDroid/src/main/res/values-ka/04-network.xml | 1 + AnkiDroid/src/main/res/values-kk/04-network.xml | 1 + AnkiDroid/src/main/res/values-km/04-network.xml | 1 + AnkiDroid/src/main/res/values-kn/04-network.xml | 1 + AnkiDroid/src/main/res/values-ko/04-network.xml | 1 + AnkiDroid/src/main/res/values-ku/04-network.xml | 1 + AnkiDroid/src/main/res/values-ky/04-network.xml | 1 + AnkiDroid/src/main/res/values-lt/04-network.xml | 1 + AnkiDroid/src/main/res/values-lv/04-network.xml | 1 + AnkiDroid/src/main/res/values-mk/04-network.xml | 1 + AnkiDroid/src/main/res/values-ml/04-network.xml | 1 + AnkiDroid/src/main/res/values-mn/04-network.xml | 1 + AnkiDroid/src/main/res/values-mr/04-network.xml | 1 + AnkiDroid/src/main/res/values-ms/04-network.xml | 1 + AnkiDroid/src/main/res/values-my/04-network.xml | 1 + AnkiDroid/src/main/res/values-nl/04-network.xml | 1 + AnkiDroid/src/main/res/values-nn/04-network.xml | 1 + AnkiDroid/src/main/res/values-no/04-network.xml | 1 + AnkiDroid/src/main/res/values-or/04-network.xml | 1 + AnkiDroid/src/main/res/values-pa/04-network.xml | 1 + AnkiDroid/src/main/res/values-pl/04-network.xml | 1 + AnkiDroid/src/main/res/values-pt-rBR/04-network.xml | 1 + AnkiDroid/src/main/res/values-pt-rPT/04-network.xml | 1 + AnkiDroid/src/main/res/values-ro/04-network.xml | 1 + AnkiDroid/src/main/res/values-ru/04-network.xml | 1 + AnkiDroid/src/main/res/values-sat/04-network.xml | 1 + AnkiDroid/src/main/res/values-sc/04-network.xml | 1 + AnkiDroid/src/main/res/values-sk/04-network.xml | 1 + AnkiDroid/src/main/res/values-sl/04-network.xml | 1 + AnkiDroid/src/main/res/values-sq/04-network.xml | 1 + AnkiDroid/src/main/res/values-sr/04-network.xml | 1 + AnkiDroid/src/main/res/values-ss/04-network.xml | 1 + AnkiDroid/src/main/res/values-sv/04-network.xml | 1 + AnkiDroid/src/main/res/values-sw/04-network.xml | 1 + AnkiDroid/src/main/res/values-ta/04-network.xml | 1 + AnkiDroid/src/main/res/values-te/04-network.xml | 1 + AnkiDroid/src/main/res/values-tg/04-network.xml | 1 + AnkiDroid/src/main/res/values-tgl/04-network.xml | 1 + AnkiDroid/src/main/res/values-th/04-network.xml | 1 + AnkiDroid/src/main/res/values-ti/04-network.xml | 1 + AnkiDroid/src/main/res/values-tn/04-network.xml | 1 + AnkiDroid/src/main/res/values-tr/04-network.xml | 1 + AnkiDroid/src/main/res/values-ts/04-network.xml | 1 + AnkiDroid/src/main/res/values-tt/04-network.xml | 1 + AnkiDroid/src/main/res/values-uk/04-network.xml | 1 + AnkiDroid/src/main/res/values-ur/04-network.xml | 1 + AnkiDroid/src/main/res/values-uz/04-network.xml | 1 + AnkiDroid/src/main/res/values-ve/04-network.xml | 1 + AnkiDroid/src/main/res/values-vi/04-network.xml | 1 + AnkiDroid/src/main/res/values-wo/04-network.xml | 1 + AnkiDroid/src/main/res/values-xh/04-network.xml | 1 + AnkiDroid/src/main/res/values-yue/04-network.xml | 1 + AnkiDroid/src/main/res/values-zh-rCN/04-network.xml | 1 + AnkiDroid/src/main/res/values-zh-rTW/04-network.xml | 1 + AnkiDroid/src/main/res/values-zu/04-network.xml | 1 + 93 files changed, 93 insertions(+) diff --git a/AnkiDroid/src/main/res/values-af/04-network.xml b/AnkiDroid/src/main/res/values-af/04-network.xml index 4583b2a56535..d6be9ffd6358 100644 --- a/AnkiDroid/src/main/res/values-af/04-network.xml +++ b/AnkiDroid/src/main/res/values-af/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-am/04-network.xml b/AnkiDroid/src/main/res/values-am/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-am/04-network.xml +++ b/AnkiDroid/src/main/res/values-am/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-ar/04-network.xml b/AnkiDroid/src/main/res/values-ar/04-network.xml index 076bee710f92..6577632120ce 100644 --- a/AnkiDroid/src/main/res/values-ar/04-network.xml +++ b/AnkiDroid/src/main/res/values-ar/04-network.xml @@ -70,6 +70,7 @@ المزامنة مزامنة كاملة من القرص المحلي تمت مزامنة المجموعة + Collection synced. Media is being synced in the background. قاعدة البيانات الخاصة بك معطوبة. يرجى إصلاحها قبل أن تحاول مزامنتها مرة أخرى.\n\nانظر في%s للحصول على معلومات حول إصلاح قاعدة البيانات الخاصة بك. محلي diff --git a/AnkiDroid/src/main/res/values-az/04-network.xml b/AnkiDroid/src/main/res/values-az/04-network.xml index 39832a199976..41091e374f71 100644 --- a/AnkiDroid/src/main/res/values-az/04-network.xml +++ b/AnkiDroid/src/main/res/values-az/04-network.xml @@ -70,6 +70,7 @@ Sinxronizasiya Yerli tam sync Kolleksiya sinxronizasiya olunmuşdur + Collection synced. Media is being synced in the background. Verilənlər bazası xarabdır.Yenidən sinxronlaşdırmağı sınamadan əvvəl düzəldin.Verilənlər bazasını təmiri haqqında məlumat üçün gözləyin: %s. Yerli diff --git a/AnkiDroid/src/main/res/values-be/04-network.xml b/AnkiDroid/src/main/res/values-be/04-network.xml index 79c2d2410b2a..96fa5d039c64 100644 --- a/AnkiDroid/src/main/res/values-be/04-network.xml +++ b/AnkiDroid/src/main/res/values-be/04-network.xml @@ -70,6 +70,7 @@ Сінхранізацыя Цалкам сінхранізавана з прыладай Калекцыя сінхранізаваная + Collection synced. Media is being synced in the background. Ваша база даных пашкоджаная. Паспрабуйце выправіць яе, а потым паўтарыце сінхранізацыю.\n\nЗвярніцеся да %s, каб даведацца больш пра выпраўленне базы даных. Лакальна diff --git a/AnkiDroid/src/main/res/values-bg/04-network.xml b/AnkiDroid/src/main/res/values-bg/04-network.xml index 7fc59a27cc0f..02618f32434a 100644 --- a/AnkiDroid/src/main/res/values-bg/04-network.xml +++ b/AnkiDroid/src/main/res/values-bg/04-network.xml @@ -70,6 +70,7 @@ Синхронизиране Пълно синхронизиране от местни Колекцията синхронизирана + Collection synced. Media is being synced in the background. Вашата база данни е повредена. Моля, поправете я преди да опитате отново да синхронизирате.\n\nВижте %s за информация относно поправравянето на Вашата база данни. Локално diff --git a/AnkiDroid/src/main/res/values-bn/04-network.xml b/AnkiDroid/src/main/res/values-bn/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-bn/04-network.xml +++ b/AnkiDroid/src/main/res/values-bn/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-ca/04-network.xml b/AnkiDroid/src/main/res/values-ca/04-network.xml index 43f109dc8667..eeb7c8cffbb8 100644 --- a/AnkiDroid/src/main/res/values-ca/04-network.xml +++ b/AnkiDroid/src/main/res/values-ca/04-network.xml @@ -70,6 +70,7 @@ Sincronització Sincronització completa dels paquets locals Col·lecció sincronitzada + Collection synced. Media is being synced in the background. La base de dades està feta malbé. Corregiu-ho abans d\'intentar una nova sincronització.\n\nVeieu %s per a obtenir informació sobre com reparar la base de dades. Local diff --git a/AnkiDroid/src/main/res/values-ckb/04-network.xml b/AnkiDroid/src/main/res/values-ckb/04-network.xml index 625fa2679d47..0521a7036f8e 100644 --- a/AnkiDroid/src/main/res/values-ckb/04-network.xml +++ b/AnkiDroid/src/main/res/values-ckb/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-cs/04-network.xml b/AnkiDroid/src/main/res/values-cs/04-network.xml index bf7844ff4206..97700bd8ecbb 100644 --- a/AnkiDroid/src/main/res/values-cs/04-network.xml +++ b/AnkiDroid/src/main/res/values-cs/04-network.xml @@ -70,6 +70,7 @@ Synchronizace Úplná synchronizace z místního úložiště Kolekce synchronizována + Collection synced. Media is being synced in the background. Databáze je poškozena. Prosím opravte jí předtím, než se ji znovu pokusíte synchronizovat.\n\nViz %s, kde jsou informace o opravě databáze. Místní diff --git a/AnkiDroid/src/main/res/values-da/04-network.xml b/AnkiDroid/src/main/res/values-da/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-da/04-network.xml +++ b/AnkiDroid/src/main/res/values-da/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-de/04-network.xml b/AnkiDroid/src/main/res/values-de/04-network.xml index 4e54c7a6cea1..5b0a16569bbc 100644 --- a/AnkiDroid/src/main/res/values-de/04-network.xml +++ b/AnkiDroid/src/main/res/values-de/04-network.xml @@ -70,6 +70,7 @@ Synchronisation Vollsynchronisation des lokalen Stapels Sammlung synchronisiert + Collection synced. Media is being synced in the background. Ihre Datenbank ist beschädigt. Bitte reparieren Sie sie vor einem erneuten Synchronisationsversuch.\n\nBesuchen Sie %s für Informationen zum Reparieren Ihrer Datenbank. Lokal diff --git a/AnkiDroid/src/main/res/values-el/04-network.xml b/AnkiDroid/src/main/res/values-el/04-network.xml index 046460eece83..56ec506d6c94 100644 --- a/AnkiDroid/src/main/res/values-el/04-network.xml +++ b/AnkiDroid/src/main/res/values-el/04-network.xml @@ -70,6 +70,7 @@ Συγχρονισμός Πλήρης συγχρονισμός από το τοπικό Η συλλογή συγχρονίστηκε + Collection synced. Media is being synced in the background. Η βάση δεδομένων είναι κατεστραμμένη. Παρακαλούμε να τη διορθώσετε πριν ξαναδοκιμάσετε να την συγχρονίσετε.\n\nΔείτε %s για πληροφορίες σχετικές με τη διόρθωση της βάσης δεδομένων σας. Τοπικά diff --git a/AnkiDroid/src/main/res/values-eo/04-network.xml b/AnkiDroid/src/main/res/values-eo/04-network.xml index 96b072f139ad..eadddf563898 100644 --- a/AnkiDroid/src/main/res/values-eo/04-network.xml +++ b/AnkiDroid/src/main/res/values-eo/04-network.xml @@ -70,6 +70,7 @@ Samtempigo Plena samtempigo al la servilo Kolekto estas sinkronigita + Collection synced. Media is being synced in the background. Via datumbazo estas difektita. Bonvolu ripari ĝin antaŭ reprovi samtempigi.\n\n Legu %s por informoj pri kiel ripari datumbazon. Loka diff --git a/AnkiDroid/src/main/res/values-es-rAR/04-network.xml b/AnkiDroid/src/main/res/values-es-rAR/04-network.xml index b7b75bd55ef1..63b1ef21a7c2 100644 --- a/AnkiDroid/src/main/res/values-es-rAR/04-network.xml +++ b/AnkiDroid/src/main/res/values-es-rAR/04-network.xml @@ -70,6 +70,7 @@ Sincronización Sincronización desde el dispositivo completa Colección sincronizada + Collection synced. Media is being synced in the background. Su base de datos está dañada. Por favor, repárela antes de intentar la sincronización nuevamente.\n\nVer %s para informarse sobre la reparación de su base de datos. Local diff --git a/AnkiDroid/src/main/res/values-es-rES/04-network.xml b/AnkiDroid/src/main/res/values-es-rES/04-network.xml index 45038d765cc6..4604ab89745d 100644 --- a/AnkiDroid/src/main/res/values-es-rES/04-network.xml +++ b/AnkiDroid/src/main/res/values-es-rES/04-network.xml @@ -70,6 +70,7 @@ Sincronización Sincronización completa desde el cliente Colección sincronizada + Collection synced. Media is being synced in the background. La base de datos está dañada. Por favor, arréglala antes de intentar volver a sincronizar.\n\nLee %s para obtener información acerca de cómo reparar la base de datos. Local diff --git a/AnkiDroid/src/main/res/values-et/04-network.xml b/AnkiDroid/src/main/res/values-et/04-network.xml index 4d1812b87612..6100ab1bf823 100644 --- a/AnkiDroid/src/main/res/values-et/04-network.xml +++ b/AnkiDroid/src/main/res/values-et/04-network.xml @@ -70,6 +70,7 @@ Sünkroonimine Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Kohalik diff --git a/AnkiDroid/src/main/res/values-eu/04-network.xml b/AnkiDroid/src/main/res/values-eu/04-network.xml index 6efeff0ff54b..f89dcfa240da 100644 --- a/AnkiDroid/src/main/res/values-eu/04-network.xml +++ b/AnkiDroid/src/main/res/values-eu/04-network.xml @@ -70,6 +70,7 @@ Sinkronizazioa Full sync from local Bilduma sinkronizatuta + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Lokala diff --git a/AnkiDroid/src/main/res/values-fa/04-network.xml b/AnkiDroid/src/main/res/values-fa/04-network.xml index 846238e504b5..a4340c425506 100644 --- a/AnkiDroid/src/main/res/values-fa/04-network.xml +++ b/AnkiDroid/src/main/res/values-fa/04-network.xml @@ -70,6 +70,7 @@ همگام سازى همگام سازی کامل از دستگاه کل مجموعه همگام سازی شد + Collection synced. Media is being synced in the background. پایگاه داده شما آسیب دیده است. لطفا قبل از همگام سازی مجدد آن را تعمیر نمایید.\n\nبرای اطلاعاتی درباره تعمیر پایگاه داده تان %s را ببینید. محلی diff --git a/AnkiDroid/src/main/res/values-fi/04-network.xml b/AnkiDroid/src/main/res/values-fi/04-network.xml index e0a63bbee6b1..16c1fa20ee44 100644 --- a/AnkiDroid/src/main/res/values-fi/04-network.xml +++ b/AnkiDroid/src/main/res/values-fi/04-network.xml @@ -70,6 +70,7 @@ Synkronointi Täysi synkronointi tästä laitteesta Kokoelma synkronoitu + Collection synced. Media is being synced in the background. Tietokanta on vioittunut. Korjaa se, ennen kuin yrität synkronoida uudelleen.\n\nKatso %s saadaksesi lisätietoja tietokannan korjaamisesta. Paikallinen diff --git a/AnkiDroid/src/main/res/values-fil/04-network.xml b/AnkiDroid/src/main/res/values-fil/04-network.xml index aa8fd5014feb..35ded74c08f6 100644 --- a/AnkiDroid/src/main/res/values-fil/04-network.xml +++ b/AnkiDroid/src/main/res/values-fil/04-network.xml @@ -70,6 +70,7 @@ Pag-synchronize Buong pag-sync mula sa lokal Nai-sync na ang mga koleksyon + Collection synced. Media is being synced in the background. Ang iyong database ay sira. Mangyaring ayusin ito bago muling subukan na i-sync.\n\n Tingnan ang %s para sa impormasyon tungkol sa pag-aayos ng iyong database. Lokal diff --git a/AnkiDroid/src/main/res/values-fr/04-network.xml b/AnkiDroid/src/main/res/values-fr/04-network.xml index 67a2c769cb38..a5df9e5ed3c9 100644 --- a/AnkiDroid/src/main/res/values-fr/04-network.xml +++ b/AnkiDroid/src/main/res/values-fr/04-network.xml @@ -70,6 +70,7 @@ Synchronisation Synchronisation complète depuis la version locale Collection synchronisée + Collection synced. Media is being synced in the background. Votre base de données est corrompue. Veuillez la réparer avant de tenter à nouveau de synchroniser.\n\nVoir %s pour plus d\'informations sur la réparation de votre base de données. Local diff --git a/AnkiDroid/src/main/res/values-fy/04-network.xml b/AnkiDroid/src/main/res/values-fy/04-network.xml index 8f2bfb8ed745..140151eb0009 100644 --- a/AnkiDroid/src/main/res/values-fy/04-network.xml +++ b/AnkiDroid/src/main/res/values-fy/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Lokaal diff --git a/AnkiDroid/src/main/res/values-ga/04-network.xml b/AnkiDroid/src/main/res/values-ga/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-ga/04-network.xml +++ b/AnkiDroid/src/main/res/values-ga/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-gl/04-network.xml b/AnkiDroid/src/main/res/values-gl/04-network.xml index b89069a0b805..320633e0c754 100644 --- a/AnkiDroid/src/main/res/values-gl/04-network.xml +++ b/AnkiDroid/src/main/res/values-gl/04-network.xml @@ -70,6 +70,7 @@ Sincronización Sincronización completa dos datos locais Colección sincronizada + Collection synced. Media is being synced in the background. Base de datos corrompida. Por favor corríxea antes de tentar sincronizar de novo.\n\nVer %s para máis información sobre como reparar a base de datos. Local diff --git a/AnkiDroid/src/main/res/values-got/04-network.xml b/AnkiDroid/src/main/res/values-got/04-network.xml index 03274f553abc..6d9aaf033044 100644 --- a/AnkiDroid/src/main/res/values-got/04-network.xml +++ b/AnkiDroid/src/main/res/values-got/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Galisa galeikona + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-gu/04-network.xml b/AnkiDroid/src/main/res/values-gu/04-network.xml index 443c47cc6f7e..033573cfc12b 100644 --- a/AnkiDroid/src/main/res/values-gu/04-network.xml +++ b/AnkiDroid/src/main/res/values-gu/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-heb/04-network.xml b/AnkiDroid/src/main/res/values-heb/04-network.xml index 044861072577..7e331b62de37 100644 --- a/AnkiDroid/src/main/res/values-heb/04-network.xml +++ b/AnkiDroid/src/main/res/values-heb/04-network.xml @@ -70,6 +70,7 @@ סנכרון סנכרון מלא מהמקומי האוסף סונכרן + Collection synced. Media is being synced in the background. מסד הנתונים שלך הושחת. נא לתקן אותו בטרם ביצוע ניסיון סנכרון חוזר.\n\nניתן לעיין ב־%s לקבלת מידע בנוגע לתיקון מסד הנתונים שלך. מקומי diff --git a/AnkiDroid/src/main/res/values-hi/04-network.xml b/AnkiDroid/src/main/res/values-hi/04-network.xml index 71d7405066df..d1236d159b30 100644 --- a/AnkiDroid/src/main/res/values-hi/04-network.xml +++ b/AnkiDroid/src/main/res/values-hi/04-network.xml @@ -70,6 +70,7 @@ समकालन स्थानीय से पूर्ण सिंक्रनाइज़ेशन संग्रह सिंक्रनाइज़ + Collection synced. Media is being synced in the background. आपका डेटाबेस दूषित है । कृपया सिंक्रनाइज़ करने के लिए पुन: प्रयास करने से पहले इसे ठीक करें. \ n \ nSee %s आपके डेटाबेस को सुधारने के बारे में जानकारी के लिए । स्थानीय diff --git a/AnkiDroid/src/main/res/values-hr/04-network.xml b/AnkiDroid/src/main/res/values-hr/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-hr/04-network.xml +++ b/AnkiDroid/src/main/res/values-hr/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-hu/04-network.xml b/AnkiDroid/src/main/res/values-hu/04-network.xml index fb848031fc86..c8b9c5bffc08 100644 --- a/AnkiDroid/src/main/res/values-hu/04-network.xml +++ b/AnkiDroid/src/main/res/values-hu/04-network.xml @@ -70,6 +70,7 @@ Szinkronizálás Teljes szinkronizáció helyből Gyűjtemény szinkronizálva + Collection synced. Media is being synced in the background. Az adatbázis sérült. Próbáld meg javítani szinkronizálás előtt!\n\nLásd a %s több információért. Helyi diff --git a/AnkiDroid/src/main/res/values-hy/04-network.xml b/AnkiDroid/src/main/res/values-hy/04-network.xml index 5283b4dfe3f2..75a84d01aa6c 100644 --- a/AnkiDroid/src/main/res/values-hy/04-network.xml +++ b/AnkiDroid/src/main/res/values-hy/04-network.xml @@ -70,6 +70,7 @@ Համաժամացում Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Սարքի diff --git a/AnkiDroid/src/main/res/values-ind/04-network.xml b/AnkiDroid/src/main/res/values-ind/04-network.xml index 4990f4fd9e81..5c9c6adbc7a1 100644 --- a/AnkiDroid/src/main/res/values-ind/04-network.xml +++ b/AnkiDroid/src/main/res/values-ind/04-network.xml @@ -70,6 +70,7 @@ Sinkronisasi Sinkronisasi penuh dari lokal Koleksi disinkronkan + Collection synced. Media is being synced in the background. Basis data Anda rusak. Perbaiki sebelum mencoba sinkronisasi lagi.\n\n Lihat %s untuk informasi tentang memperbaiki basis data Anda. Lokal diff --git a/AnkiDroid/src/main/res/values-is/04-network.xml b/AnkiDroid/src/main/res/values-is/04-network.xml index 4788aadc6dff..bd076af38437 100644 --- a/AnkiDroid/src/main/res/values-is/04-network.xml +++ b/AnkiDroid/src/main/res/values-is/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-it/04-network.xml b/AnkiDroid/src/main/res/values-it/04-network.xml index bb34bf02aec6..1f5daba1fb8c 100644 --- a/AnkiDroid/src/main/res/values-it/04-network.xml +++ b/AnkiDroid/src/main/res/values-it/04-network.xml @@ -70,6 +70,7 @@ Sincronizzazione Sincronizzazione completa da locale Collezione sincronizzata + Collection synced. Media is being synced in the background. Il tuo database è corrotto. Riparalo prima di provare nuovamente a sincronizzare.\n\nVedi %s per informazioni su come riparare il database. Locale diff --git a/AnkiDroid/src/main/res/values-iw/04-network.xml b/AnkiDroid/src/main/res/values-iw/04-network.xml index 044861072577..7e331b62de37 100644 --- a/AnkiDroid/src/main/res/values-iw/04-network.xml +++ b/AnkiDroid/src/main/res/values-iw/04-network.xml @@ -70,6 +70,7 @@ סנכרון סנכרון מלא מהמקומי האוסף סונכרן + Collection synced. Media is being synced in the background. מסד הנתונים שלך הושחת. נא לתקן אותו בטרם ביצוע ניסיון סנכרון חוזר.\n\nניתן לעיין ב־%s לקבלת מידע בנוגע לתיקון מסד הנתונים שלך. מקומי diff --git a/AnkiDroid/src/main/res/values-ja/04-network.xml b/AnkiDroid/src/main/res/values-ja/04-network.xml index 2b817f5767c8..7d119f9063a6 100644 --- a/AnkiDroid/src/main/res/values-ja/04-network.xml +++ b/AnkiDroid/src/main/res/values-ja/04-network.xml @@ -70,6 +70,7 @@ 同期 この端末側のコレクションによる完全同期が完了しました コレクションの同期が完了しました + Collection synced. Media is being synced in the background. データベースが破損しています。同期を再試行する前にデータベースを修復してください。修復に関する情報は %s を参照してください。 ローカル diff --git a/AnkiDroid/src/main/res/values-jv/04-network.xml b/AnkiDroid/src/main/res/values-jv/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-jv/04-network.xml +++ b/AnkiDroid/src/main/res/values-jv/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-ka/04-network.xml b/AnkiDroid/src/main/res/values-ka/04-network.xml index d836b8889ff6..b411f7ac0aeb 100644 --- a/AnkiDroid/src/main/res/values-ka/04-network.xml +++ b/AnkiDroid/src/main/res/values-ka/04-network.xml @@ -70,6 +70,7 @@ სინქრონიზაცია სრული სინქრონიზაცია ლოკალურიდან კოლექციის სინქრონიზაცია წარმატებით განხორციელდა + Collection synced. Media is being synced in the background. თქვენი მონაცემთა ბაზა დაზიანებულია. გთხოვთ, სინქრონიზების ხელახლა ცდამდე პრობლემა აღმოფხვრათ.\n\nმონაცემთა ბაზის გამოსასწორებლად საჭირო ინფორმაციისთვის იხილეთ %s. ლოკალური diff --git a/AnkiDroid/src/main/res/values-kk/04-network.xml b/AnkiDroid/src/main/res/values-kk/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-kk/04-network.xml +++ b/AnkiDroid/src/main/res/values-kk/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-km/04-network.xml b/AnkiDroid/src/main/res/values-km/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-km/04-network.xml +++ b/AnkiDroid/src/main/res/values-km/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-kn/04-network.xml b/AnkiDroid/src/main/res/values-kn/04-network.xml index e6e437b410fc..9adaf8168205 100644 --- a/AnkiDroid/src/main/res/values-kn/04-network.xml +++ b/AnkiDroid/src/main/res/values-kn/04-network.xml @@ -70,6 +70,7 @@ ಸಿಂಕ್ರೊನೈಸೇಶನ್ ಸ್ಥಳೀಯದಿಂದ ಪೂರ್ಣ ಸಿಂಕ್ ಸಂಗ್ರಹವನ್ನು ಸಿಂಕ್ರೊನೈಸ್ ಮಾಡಲಾಗಿದೆ + Collection synced. Media is being synced in the background. ನಿಮ್ಮ ಡೇಟಾಬೇಸ್ ದೋಷಪೂರಿತವಾಗಿದೆ. ಮತ್ತೊಮ್ಮೆ ಸಿಂಕ್ ಮಾಡಲು ಪ್ರಯತ್ನಿಸುವ ಮೊದಲು ಅದನ್ನು ಸರಿಪಡಿಸಿ.\n\nನಿಮ್ಮ ಡೇಟಾಬೇಸ್ ಅನ್ನು ದುರಸ್ತಿ ಮಾಡುವ ಕುರಿತು ಮಾಹಿತಿಗಾಗಿ %s ಅನ್ನು ನೋಡಿ. ಸ್ಥಳೀಯ diff --git a/AnkiDroid/src/main/res/values-ko/04-network.xml b/AnkiDroid/src/main/res/values-ko/04-network.xml index 62c484f1db2d..a4efe70e1712 100644 --- a/AnkiDroid/src/main/res/values-ko/04-network.xml +++ b/AnkiDroid/src/main/res/values-ko/04-network.xml @@ -70,6 +70,7 @@ 동기화 기기 기준 전체 동기화 컬렉션 동기화됨 + Collection synced. Media is being synced in the background. 데이터베이스가 손상되었습니다. 동기화 재시도 전에 문제를 수정하십시오. \n\n 데이터베이스 수정을 위해서는 %s 를 참고하세요. 장치 diff --git a/AnkiDroid/src/main/res/values-ku/04-network.xml b/AnkiDroid/src/main/res/values-ku/04-network.xml index 56fe5ae030eb..4e0e29358d87 100644 --- a/AnkiDroid/src/main/res/values-ku/04-network.xml +++ b/AnkiDroid/src/main/res/values-ku/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-ky/04-network.xml b/AnkiDroid/src/main/res/values-ky/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-ky/04-network.xml +++ b/AnkiDroid/src/main/res/values-ky/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-lt/04-network.xml b/AnkiDroid/src/main/res/values-lt/04-network.xml index e44ec7528e06..42cb3d1ec079 100644 --- a/AnkiDroid/src/main/res/values-lt/04-network.xml +++ b/AnkiDroid/src/main/res/values-lt/04-network.xml @@ -70,6 +70,7 @@ Sinchronizavimas Išsamus sinchronizavimas iš įrenginio Kolekcija susinchronizuota + Collection synced. Media is being synced in the background. Jūsų duomenų bazė yra sugadinta. Prašome ją pataisyti prieš bandydami ją dar kartą susinchronizuoti.\n\nDaugiau informacijos apie duomenų bazės taisymą rasite %s. Įrenginio diff --git a/AnkiDroid/src/main/res/values-lv/04-network.xml b/AnkiDroid/src/main/res/values-lv/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-lv/04-network.xml +++ b/AnkiDroid/src/main/res/values-lv/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-mk/04-network.xml b/AnkiDroid/src/main/res/values-mk/04-network.xml index 96eb40091b32..fe10cb13aa5f 100644 --- a/AnkiDroid/src/main/res/values-mk/04-network.xml +++ b/AnkiDroid/src/main/res/values-mk/04-network.xml @@ -70,6 +70,7 @@ Синхронизација Целосна синхронизација од локално Колекцијата е синхронизирана + Collection synced. Media is being synced in the background. Вашата база на податоци е корумпирана. Ве молиме поправете го пред да се обидете повторно да синхронизирате.\n\nВидете %s за информации за поправање на вашата база на податоци. Локален diff --git a/AnkiDroid/src/main/res/values-ml/04-network.xml b/AnkiDroid/src/main/res/values-ml/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-ml/04-network.xml +++ b/AnkiDroid/src/main/res/values-ml/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-mn/04-network.xml b/AnkiDroid/src/main/res/values-mn/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-mn/04-network.xml +++ b/AnkiDroid/src/main/res/values-mn/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-mr/04-network.xml b/AnkiDroid/src/main/res/values-mr/04-network.xml index f1c7d59f41cb..82800f45c7c5 100644 --- a/AnkiDroid/src/main/res/values-mr/04-network.xml +++ b/AnkiDroid/src/main/res/values-mr/04-network.xml @@ -70,6 +70,7 @@ सिंक्रोनाइझेशन स्थानिक कडून पूर्ण संकालन संकलन समक्रमित केले + Collection synced. Media is being synced in the background. आपला डेटाबेस दूषित झाला आहे. कृपया पुन्हा संकालनाचा प्रयत्न करण्यापूर्वी ते निश्चित करा. Your \n\n आपल्या डेटाबेसच्या दुरुस्तीबद्दल माहितीसाठी%s पहा. स्थानिक diff --git a/AnkiDroid/src/main/res/values-ms/04-network.xml b/AnkiDroid/src/main/res/values-ms/04-network.xml index 558c5c2d1da0..2c756ece680d 100644 --- a/AnkiDroid/src/main/res/values-ms/04-network.xml +++ b/AnkiDroid/src/main/res/values-ms/04-network.xml @@ -70,6 +70,7 @@ Penyegerakan Penyegerakan penuh daripada tempatan Koleksi telah disegerakkan + Collection synced. Media is being synced in the background. Pangkalan data anda rosak. Sila membaikinya sebelum cuba penyegerakan lagi.\n\nLihat %s untuk maklumat tentang membaiki pangkalan data anda. Tempatan diff --git a/AnkiDroid/src/main/res/values-my/04-network.xml b/AnkiDroid/src/main/res/values-my/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-my/04-network.xml +++ b/AnkiDroid/src/main/res/values-my/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-nl/04-network.xml b/AnkiDroid/src/main/res/values-nl/04-network.xml index 2e19b6eafd97..8a1341d98f22 100644 --- a/AnkiDroid/src/main/res/values-nl/04-network.xml +++ b/AnkiDroid/src/main/res/values-nl/04-network.xml @@ -70,6 +70,7 @@ Synchronisatie Volledige synchronisatie vanaf lokale kant Collectie gesynchroniseerd + Collection synced. Media is being synced in the background. Uw database is beschadigd. Corrigeer dit en probeer het opnieuw te synchroniseren.\n\nZie %s voor meer informatie over het herstellen van je database. Lokaal diff --git a/AnkiDroid/src/main/res/values-nn/04-network.xml b/AnkiDroid/src/main/res/values-nn/04-network.xml index 0ed79dbcebb6..202567b8318c 100644 --- a/AnkiDroid/src/main/res/values-nn/04-network.xml +++ b/AnkiDroid/src/main/res/values-nn/04-network.xml @@ -70,6 +70,7 @@ Synkronisering Full synkronisering fra lokal Samling synkronisert + Collection synced. Media is being synced in the background. Databasen din er ødelagt. Vennligst fiks den før du prøver å synkronisere på nytt.\n\nSee %s for informasjon om å reparere databaser. Lokalt diff --git a/AnkiDroid/src/main/res/values-no/04-network.xml b/AnkiDroid/src/main/res/values-no/04-network.xml index 588e0b005ce6..58c6abf4c3a3 100644 --- a/AnkiDroid/src/main/res/values-no/04-network.xml +++ b/AnkiDroid/src/main/res/values-no/04-network.xml @@ -70,6 +70,7 @@ Synkronisering Full synkronisering fra lokal Samling synkronisert + Collection synced. Media is being synced in the background. Databasen din er ødelagt. Vennligst fiks den før du prøver å synkronisere på nytt.\n\nSee %s for informasjon om å reparere databaser. Lokalt diff --git a/AnkiDroid/src/main/res/values-or/04-network.xml b/AnkiDroid/src/main/res/values-or/04-network.xml index 6af7bb12d361..aafe7d55f331 100644 --- a/AnkiDroid/src/main/res/values-or/04-network.xml +++ b/AnkiDroid/src/main/res/values-or/04-network.xml @@ -70,6 +70,7 @@ ସୀଙ୍କ୍ରୋନାଇଜେଶନ୍ ସ୍ଥାନୀୟ ଠାରୁ ପୂର୍ଣ୍ଣ ସୀଙ୍କ୍ କରାଗଲା ସଂଗ୍ରହ ସୀଙ୍କ୍ରୋନାଇଜ୍ ହୋଇଛି + Collection synced. Media is being synced in the background. ଆପଣଙ୍କର ଡାଟାବେସ୍ ଭ୍ରଷ୍ଟ ଅଟେ। ସୀଙ୍କ୍ କରିବାକୁ ପୁନର୍ବାର ଚେଷ୍ଟା କରିବା ଆଗରୁ ଦୟାକରି ଏହାକୁ ଠିକ୍ କରିନିଅନ୍ତୁ।\n\nଆପଣଙ୍କର ଡାଟାବେସ୍ ମରାମତି ବିଷୟରେ ସୂଚନା ପାଇଁ %s ଦେଖନ୍ତୁ। ସ୍ଥାନୀୟ diff --git a/AnkiDroid/src/main/res/values-pa/04-network.xml b/AnkiDroid/src/main/res/values-pa/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-pa/04-network.xml +++ b/AnkiDroid/src/main/res/values-pa/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-pl/04-network.xml b/AnkiDroid/src/main/res/values-pl/04-network.xml index 7ae7aefdd1ca..088c6b4154c0 100644 --- a/AnkiDroid/src/main/res/values-pl/04-network.xml +++ b/AnkiDroid/src/main/res/values-pl/04-network.xml @@ -70,6 +70,7 @@ Synchronizacja Pełna synchronizacja do serwera Kolekcja zsynchronizowana + Collection synced. Media is being synced in the background. Twoja baza danych jest uszkodzona. Napraw ją, zanim ponownie spróbujesz synchronizacji.\n\nPod adresem %s znajdziesz informacje o naprawianiu bazy danych. Lokalne diff --git a/AnkiDroid/src/main/res/values-pt-rBR/04-network.xml b/AnkiDroid/src/main/res/values-pt-rBR/04-network.xml index 7632000d7f6b..69c122a98dbb 100644 --- a/AnkiDroid/src/main/res/values-pt-rBR/04-network.xml +++ b/AnkiDroid/src/main/res/values-pt-rBR/04-network.xml @@ -70,6 +70,7 @@ Sincronização Sincronização completa do local Coleção sincronizada + Collection synced. Media is being synced in the background. Seu banco de dados está corrompido. Por favor corrija-o antes de tentar novamente a sincronização.\n\nVeja %s para obter informações sobre como reparar o banco de dados. Local diff --git a/AnkiDroid/src/main/res/values-pt-rPT/04-network.xml b/AnkiDroid/src/main/res/values-pt-rPT/04-network.xml index 43db876fcc98..bb2dba48ff21 100644 --- a/AnkiDroid/src/main/res/values-pt-rPT/04-network.xml +++ b/AnkiDroid/src/main/res/values-pt-rPT/04-network.xml @@ -70,6 +70,7 @@ Sincronização Sincronização completa a partir dos dados locais Coleção sincronizada + Collection synced. Media is being synced in the background. A sua base de dados está corrompida. Por favor corrija-a antes de tentar novamente uma sincronização.\n\nVeja %s para obter informações sobre como reparar a base de dados. Local diff --git a/AnkiDroid/src/main/res/values-ro/04-network.xml b/AnkiDroid/src/main/res/values-ro/04-network.xml index 1940cf0cc392..5d4d5daa878a 100644 --- a/AnkiDroid/src/main/res/values-ro/04-network.xml +++ b/AnkiDroid/src/main/res/values-ro/04-network.xml @@ -70,6 +70,7 @@ Sincronizare Sincronizare completă din local Colectia sincronizata + Collection synced. Media is being synced in the background. Baza de date este corupta. Vă rugăm să o refaceti înainte de a încerca din nou să sync.\n\nSee %s pentru informaţii despre repararea bazei de date. Local diff --git a/AnkiDroid/src/main/res/values-ru/04-network.xml b/AnkiDroid/src/main/res/values-ru/04-network.xml index 67327f8b5473..4347dca611e1 100644 --- a/AnkiDroid/src/main/res/values-ru/04-network.xml +++ b/AnkiDroid/src/main/res/values-ru/04-network.xml @@ -70,6 +70,7 @@ Синхронизация Полностью синхронизировано с устройством Коллекция синхронизирована + Collection synced. Media is being synced in the background. База данных повреждена. Попробуйте исправить её и синхронизироваться опять.\n\nОб исправлении см. %s. Локальную diff --git a/AnkiDroid/src/main/res/values-sat/04-network.xml b/AnkiDroid/src/main/res/values-sat/04-network.xml index 297e1aaa8e67..5db4550a4b79 100644 --- a/AnkiDroid/src/main/res/values-sat/04-network.xml +++ b/AnkiDroid/src/main/res/values-sat/04-network.xml @@ -70,6 +70,7 @@ ᱟᱭᱩᱨ ᱤᱫᱤᱜ ᱪᱟᱹᱞᱩᱜ ᱠᱟᱱᱟ ᱞᱚᱠᱟᱞ ᱠᱷᱚᱱ ᱟᱹᱭᱩᱨ ᱢᱤᱫᱚᱜ ᱴᱩᱢᱟᱹᱞ ᱟᱹᱭᱩᱨ ᱢᱤᱫ + Collection synced. Media is being synced in the background. ᱥᱟᱫᱽᱠᱷᱤᱭᱟᱹ ᱵᱟᱹᱭᱥᱟᱣ ᱨᱟᱹᱯᱩᱫ ᱮᱱᱟ ᱾ ᱟᱹᱭᱩᱨ ᱢᱤᱫ ᱢᱟᱲᱟᱹᱝ ᱨᱮ ᱴᱷᱤᱠ ᱢᱮ ᱾ ᱥᱟᱫᱽᱠᱷᱤᱭᱟᱹ ᱵᱟᱹᱭᱥᱟᱣ ᱴᱷᱤᱠ ᱞᱟᱹᱜᱤᱫ \n\nᱧᱮᱞᱢᱮ %s ᱾ ᱱᱚᱰᱮᱱᱟᱜ diff --git a/AnkiDroid/src/main/res/values-sc/04-network.xml b/AnkiDroid/src/main/res/values-sc/04-network.xml index a8a678ac36fa..3eb32cc27838 100644 --- a/AnkiDroid/src/main/res/values-sc/04-network.xml +++ b/AnkiDroid/src/main/res/values-sc/04-network.xml @@ -70,6 +70,7 @@ Sincronizatzione Sincronizatzione totale dae locale Colletzione sincronizada + Collection synced. Media is being synced in the background. Sa base de datos tua est corrùmpida. Acontza·la in antis de torrare a proare a sincronizare.\n \n Pòmpia·ti %s pro informatziones in subra de comente acontzare sa base de datos tua. diff --git a/AnkiDroid/src/main/res/values-sk/04-network.xml b/AnkiDroid/src/main/res/values-sk/04-network.xml index d267927945e3..72eabdf88b45 100644 --- a/AnkiDroid/src/main/res/values-sk/04-network.xml +++ b/AnkiDroid/src/main/res/values-sk/04-network.xml @@ -70,6 +70,7 @@ Synchronizácia Úplná synchronizácia z AnkiDroid na server Ankiweb Kolekcia synchronizovaná + Collection synced. Media is being synced in the background. Vaša databáza je poškodená. Prosím opravte ju pred opätovným pokusom o synchronizáciu.\n\nPozrite si %s pre informácie o oprave databázy. Miestnu diff --git a/AnkiDroid/src/main/res/values-sl/04-network.xml b/AnkiDroid/src/main/res/values-sl/04-network.xml index 74673cb82f91..571f4217b99b 100644 --- a/AnkiDroid/src/main/res/values-sl/04-network.xml +++ b/AnkiDroid/src/main/res/values-sl/04-network.xml @@ -70,6 +70,7 @@ Sinhronizacija Polna sin. iz lokalne pom. naprave Zbirka sinhronizirana + Collection synced. Media is being synced in the background. Vaša podatkovna zbirka je pokvarjena. Pred ponovnim poizkusom sinhronizacije jo popravite.\n\nZa informacije o popravljanju podatkovne zbirke glejte %s. Lokalno diff --git a/AnkiDroid/src/main/res/values-sq/04-network.xml b/AnkiDroid/src/main/res/values-sq/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-sq/04-network.xml +++ b/AnkiDroid/src/main/res/values-sq/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-sr/04-network.xml b/AnkiDroid/src/main/res/values-sr/04-network.xml index fa0a7c7a713f..bbbef82b73cc 100644 --- a/AnkiDroid/src/main/res/values-sr/04-network.xml +++ b/AnkiDroid/src/main/res/values-sr/04-network.xml @@ -70,6 +70,7 @@ Синхронизација Потпуно синхронизовано са локалним подацима Колекција синхронизована + Collection synced. Media is being synced in the background. Ваша база података је оштећена. Исправите оштећења пре него што поновите покушај синхронизације.\n\nПогледајте %s о обнављању базе података. Локално diff --git a/AnkiDroid/src/main/res/values-ss/04-network.xml b/AnkiDroid/src/main/res/values-ss/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-ss/04-network.xml +++ b/AnkiDroid/src/main/res/values-ss/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-sv/04-network.xml b/AnkiDroid/src/main/res/values-sv/04-network.xml index 8e4db7f5cf0e..8338897b2dc6 100644 --- a/AnkiDroid/src/main/res/values-sv/04-network.xml +++ b/AnkiDroid/src/main/res/values-sv/04-network.xml @@ -70,6 +70,7 @@ Synkronisering Fullständig synkronisering från lokal sida Samling synkroniserad + Collection synced. Media is being synced in the background. Din databas är korrupt. Var vänlig och åtgärda detta innan du försöker synkronisera igen.\n\nSe %s för mer information om att reparera din databas. Lokal diff --git a/AnkiDroid/src/main/res/values-sw/04-network.xml b/AnkiDroid/src/main/res/values-sw/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-sw/04-network.xml +++ b/AnkiDroid/src/main/res/values-sw/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-ta/04-network.xml b/AnkiDroid/src/main/res/values-ta/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-ta/04-network.xml +++ b/AnkiDroid/src/main/res/values-ta/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-te/04-network.xml b/AnkiDroid/src/main/res/values-te/04-network.xml index c506d708a071..0a951117c8e1 100644 --- a/AnkiDroid/src/main/res/values-te/04-network.xml +++ b/AnkiDroid/src/main/res/values-te/04-network.xml @@ -70,6 +70,7 @@ సమకాలీకరణ స్థానికం నుండి పూర్తి సమకాలీకరణ సేకరణ సమకాలీకరించబడింది + Collection synced. Media is being synced in the background. మీ డేటాబేస్ అవినీతి ఉంది. దయచేసి మళ్లీ సమకాలీకరించడానికి ప్రయత్నించే ముందు దాన్ని పరిష్కరించండి.\n\n మీ డేటాబేస్ను సరిచేయడానికి సమాచారం కోసం %s వీక్షించండి. స్థానిక diff --git a/AnkiDroid/src/main/res/values-tg/04-network.xml b/AnkiDroid/src/main/res/values-tg/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-tg/04-network.xml +++ b/AnkiDroid/src/main/res/values-tg/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-tgl/04-network.xml b/AnkiDroid/src/main/res/values-tgl/04-network.xml index 30cee0714431..e8c04ca49609 100644 --- a/AnkiDroid/src/main/res/values-tgl/04-network.xml +++ b/AnkiDroid/src/main/res/values-tgl/04-network.xml @@ -70,6 +70,7 @@ Pagsisingkronisa Buong pag-sisingkronisa mula sa lokal Na-isingkronisa na ang koleksyon + Collection synced. Media is being synced in the background. Ang iyong talahanayan ng datos ay may sira. Mangyaring ayusin ito bago muling subukan na i-singkronisa.\n\n Tingnan ang %s para sa impormasyon tungkol sa pag-aayos ng iyong talahanayan ng datos. Lokal diff --git a/AnkiDroid/src/main/res/values-th/04-network.xml b/AnkiDroid/src/main/res/values-th/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-th/04-network.xml +++ b/AnkiDroid/src/main/res/values-th/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-ti/04-network.xml b/AnkiDroid/src/main/res/values-ti/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-ti/04-network.xml +++ b/AnkiDroid/src/main/res/values-ti/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-tn/04-network.xml b/AnkiDroid/src/main/res/values-tn/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-tn/04-network.xml +++ b/AnkiDroid/src/main/res/values-tn/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-tr/04-network.xml b/AnkiDroid/src/main/res/values-tr/04-network.xml index fd3fddcc4a3d..1d9e27ed66dd 100644 --- a/AnkiDroid/src/main/res/values-tr/04-network.xml +++ b/AnkiDroid/src/main/res/values-tr/04-network.xml @@ -70,6 +70,7 @@ Senkronizasyon Yerelden tam senkronizasyon Koleksiyon senkronize edildi + Collection synced. Media is being synced in the background. Veritabanınız bozuk. Lütfen eşitlemeyi yeniden denemeden önce onu düzeltin.\n\nVeritabanınızı onarmak hakkında bilgi için %s bakın. Yerel diff --git a/AnkiDroid/src/main/res/values-ts/04-network.xml b/AnkiDroid/src/main/res/values-ts/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-ts/04-network.xml +++ b/AnkiDroid/src/main/res/values-ts/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-tt/04-network.xml b/AnkiDroid/src/main/res/values-tt/04-network.xml index 2cc941d10602..ef8dc7e8b7d1 100644 --- a/AnkiDroid/src/main/res/values-tt/04-network.xml +++ b/AnkiDroid/src/main/res/values-tt/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-uk/04-network.xml b/AnkiDroid/src/main/res/values-uk/04-network.xml index 10d878162b11..bd0030fd3154 100644 --- a/AnkiDroid/src/main/res/values-uk/04-network.xml +++ b/AnkiDroid/src/main/res/values-uk/04-network.xml @@ -70,6 +70,7 @@ Синхронізація Повна синхронізація з пристрою Збірка синхронізована + Collection synced. Media is being synced in the background. Ваша база даних пошкоджена. Будь ласка, виправте її перед спробою повторної синхронізації.\n\nДивіться %s для інформації про виправлення бази даних. Локально diff --git a/AnkiDroid/src/main/res/values-ur/04-network.xml b/AnkiDroid/src/main/res/values-ur/04-network.xml index b81983c4a487..9856a1428d55 100644 --- a/AnkiDroid/src/main/res/values-ur/04-network.xml +++ b/AnkiDroid/src/main/res/values-ur/04-network.xml @@ -70,6 +70,7 @@ ہم وقت سازی مقامی سے مکمل مطابقت پذیری۔ مجموعہ مطابقت پذیر + Collection synced. Media is being synced in the background. آپ کا ڈیٹا بیس کرپٹ ہے۔ براہ کرم مطابقت پذیری کی دوبارہ کوشش کرنے سے پہلے اسے ٹھیک کریں۔\n\nاپنے ڈیٹا بیس کی مرمت کے بارے میں معلومات کے لیے %s دیکھیں۔ مقامی diff --git a/AnkiDroid/src/main/res/values-uz/04-network.xml b/AnkiDroid/src/main/res/values-uz/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-uz/04-network.xml +++ b/AnkiDroid/src/main/res/values-uz/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-ve/04-network.xml b/AnkiDroid/src/main/res/values-ve/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-ve/04-network.xml +++ b/AnkiDroid/src/main/res/values-ve/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-vi/04-network.xml b/AnkiDroid/src/main/res/values-vi/04-network.xml index 8511231032aa..6bfd3c7ae90a 100644 --- a/AnkiDroid/src/main/res/values-vi/04-network.xml +++ b/AnkiDroid/src/main/res/values-vi/04-network.xml @@ -70,6 +70,7 @@ Đồng bộ Đồng bộ hoàn toàn từ thiết bị Bộ sưu tập đã được đồng bộ + Collection synced. Media is being synced in the background. CSDL của bạn đã hỏng. Xin sửa nó trước khi thử đồng bộ lại.\n\nXem %s để biết thông tin về sửa chữa CSDL. Trên thiết bị diff --git a/AnkiDroid/src/main/res/values-wo/04-network.xml b/AnkiDroid/src/main/res/values-wo/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-wo/04-network.xml +++ b/AnkiDroid/src/main/res/values-wo/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-xh/04-network.xml b/AnkiDroid/src/main/res/values-xh/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-xh/04-network.xml +++ b/AnkiDroid/src/main/res/values-xh/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-yue/04-network.xml b/AnkiDroid/src/main/res/values-yue/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-yue/04-network.xml +++ b/AnkiDroid/src/main/res/values-yue/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local diff --git a/AnkiDroid/src/main/res/values-zh-rCN/04-network.xml b/AnkiDroid/src/main/res/values-zh-rCN/04-network.xml index 1bbed7313cbe..4b812bfc6308 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/04-network.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/04-network.xml @@ -70,6 +70,7 @@ 同步 从本地完全同步 同步完成 + Collection synced. Media is being synced in the background. 您的数据库已损坏。请修复后再尝试同步。\n\n查阅%s关于修复数据库的信息。 本地 diff --git a/AnkiDroid/src/main/res/values-zh-rTW/04-network.xml b/AnkiDroid/src/main/res/values-zh-rTW/04-network.xml index 53b4705e1f67..508b52db813d 100644 --- a/AnkiDroid/src/main/res/values-zh-rTW/04-network.xml +++ b/AnkiDroid/src/main/res/values-zh-rTW/04-network.xml @@ -70,6 +70,7 @@ 同步 由本地端完整同步 集合同步完成 + Collection synced. Media is being synced in the background. 你的資料庫已損壞。請先嘗試修復然後再試一次。\n\n關於如何修復資料庫,請參考 %s 。 本機 diff --git a/AnkiDroid/src/main/res/values-zu/04-network.xml b/AnkiDroid/src/main/res/values-zu/04-network.xml index 55cc45573e1f..f6478d020b6e 100644 --- a/AnkiDroid/src/main/res/values-zu/04-network.xml +++ b/AnkiDroid/src/main/res/values-zu/04-network.xml @@ -70,6 +70,7 @@ Synchronization Full sync from local Collection synchronized + Collection synced. Media is being synced in the background. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. Local From 03fecf3732adac3ef4753134dbf88952ccd1e6fc Mon Sep 17 00:00:00 2001 From: AnkiDroid Translations Date: Mon, 10 Jun 2024 13:29:05 +0000 Subject: [PATCH 067/138] Updated strings from Crowdin --- AnkiDroid/src/main/res/values-zh-rCN/04-network.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AnkiDroid/src/main/res/values-zh-rCN/04-network.xml b/AnkiDroid/src/main/res/values-zh-rCN/04-network.xml index 4b812bfc6308..6a4cb03aedfb 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/04-network.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/04-network.xml @@ -70,7 +70,7 @@ 同步 从本地完全同步 同步完成 - Collection synced. Media is being synced in the background. + 牌组集合已同步。正在后台同步媒体文件。 您的数据库已损坏。请修复后再尝试同步。\n\n查阅%s关于修复数据库的信息。 本地 From 7072592247be57f913023e69f918146c454e3596 Mon Sep 17 00:00:00 2001 From: Moreno <154519856+morenotropical@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:11:35 -0300 Subject: [PATCH 068/138] add next card due message --- .../java/com/ichi2/anki/pages/CongratsPage.kt | 42 ++++++++++++++++--- .../main/java/com/ichi2/anki/utils/Time.kt | 6 +-- AnkiDroid/src/main/res/values/01-core.xml | 1 + 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/pages/CongratsPage.kt b/AnkiDroid/src/main/java/com/ichi2/anki/pages/CongratsPage.kt index 5349e471a72e..0e1bf95b3945 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/pages/CongratsPage.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/pages/CongratsPage.kt @@ -15,7 +15,6 @@ */ package com.ichi2.anki.pages -import android.app.Activity import android.content.Context import android.content.Intent import android.os.Bundle @@ -23,6 +22,7 @@ import android.view.View import android.webkit.JavascriptInterface import androidx.appcompat.app.AlertDialog import androidx.fragment.app.DialogFragment +import androidx.fragment.app.FragmentActivity import androidx.fragment.app.viewModels import androidx.lifecycle.ViewModel import androidx.lifecycle.flowWithLifecycle @@ -30,6 +30,7 @@ import androidx.lifecycle.lifecycleScope import anki.collection.OpChanges import com.google.android.material.appbar.MaterialToolbar import com.ichi2.anki.CollectionManager +import com.ichi2.anki.CollectionManager.TR import com.ichi2.anki.CollectionManager.withCol import com.ichi2.anki.DeckPicker import com.ichi2.anki.FilteredDeckOptions @@ -40,9 +41,13 @@ import com.ichi2.anki.SingleFragmentActivity import com.ichi2.anki.StudyOptionsActivity import com.ichi2.anki.dialogs.customstudy.CustomStudyDialog import com.ichi2.anki.launchCatchingIO +import com.ichi2.anki.launchCatchingTask import com.ichi2.anki.preferences.sharedPrefs import com.ichi2.anki.showThemedToast import com.ichi2.anki.snackbar.showSnackbar +import com.ichi2.anki.utils.SECONDS_PER_DAY +import com.ichi2.anki.utils.TIME_HOUR +import com.ichi2.anki.utils.TIME_MINUTE import com.ichi2.libanki.ChangeManager import com.ichi2.libanki.DeckId import com.ichi2.libanki.undoableOp @@ -50,6 +55,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import timber.log.Timber +import kotlin.math.round class CongratsPage : PageFragment(), @@ -183,15 +189,18 @@ class CongratsPage : private fun displayNewCongratsScreen(context: Context): Boolean = context.sharedPrefs().getBoolean("new_congrats_screen", false) - fun display(activity: Activity) { + fun display(activity: FragmentActivity) { if (displayNewCongratsScreen(activity)) { activity.startActivity(getIntent(activity)) } else { - showThemedToast(activity, R.string.studyoptions_congrats_finished, false) + activity.launchCatchingTask { + val message = getDeckFinishedMessage(activity) + showThemedToast(activity, message, false) + } } } - fun onReviewsCompleted(activity: Activity, cardsInDeck: Boolean) { + fun onReviewsCompleted(activity: FragmentActivity, cardsInDeck: Boolean) { if (displayNewCongratsScreen(activity)) { activity.startActivity(getIntent(activity)) return @@ -199,12 +208,35 @@ class CongratsPage : // Show a message when reviewing has finished if (cardsInDeck) { - activity.showSnackbar(R.string.studyoptions_congrats_finished) + activity.launchCatchingTask { + val message = getDeckFinishedMessage(activity) + activity.showSnackbar(message) + } } else { activity.showSnackbar(R.string.studyoptions_no_cards_due) } } + // based in https://github.com/ankitects/anki/blob/9b4dd54312de8798a3f2bee07892bb3a488d1f9b/ts/routes/congrats/lib.ts#L8C17-L8C34 + private suspend fun getDeckFinishedMessage(activity: FragmentActivity): String { + val info = withCol { sched.congratulationsInfo() } + val secsUntilNextLearn = info.secsUntilNextLearn + if (secsUntilNextLearn >= SECONDS_PER_DAY) { + return activity.getString(R.string.studyoptions_congrats_finished) + } + // https://github.com/ankitects/anki/blob/9b4dd54312de8798a3f2bee07892bb3a488d1f9b/ts/lib/tslib/time.ts#L22 + val (unit, amount) = if (secsUntilNextLearn < TIME_MINUTE) { + "seconds" to secsUntilNextLearn.toDouble() + } else if (secsUntilNextLearn < TIME_HOUR) { + "minutes" to secsUntilNextLearn / TIME_MINUTE + } else { + "hours" to secsUntilNextLearn / TIME_HOUR + } + + val nextLearnDue = TR.schedulingNextLearnDue(unit, round(amount).toInt()) + return activity.getString(R.string.studyoptions_congrats_next_due_in, nextLearnDue) + } + fun DeckPicker.onDeckCompleted() { startActivity(getIntent(this)) } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/utils/Time.kt b/AnkiDroid/src/main/java/com/ichi2/anki/utils/Time.kt index 819b751fdc0a..0483df1e3d78 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/utils/Time.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/utils/Time.kt @@ -37,9 +37,9 @@ private const val TIME_DAY_LONG = 24 * TIME_HOUR_LONG // These are doubles on purpose because we want a rounded, not integer result later. // Use values from Anki Desktop: // https://github.com/ankitects/anki/blob/05cc47a5d3d48851267cda47f62af79f468eb028/rslib/src/sched/timespan.rs#L83 -private const val TIME_MINUTE = 60.0 // seconds -private const val TIME_HOUR = 60.0 * TIME_MINUTE -private const val TIME_DAY = 24.0 * TIME_HOUR +const val TIME_MINUTE = 60.0 // seconds +const val TIME_HOUR = 60.0 * TIME_MINUTE +const val TIME_DAY = 24.0 * TIME_HOUR private const val TIME_MONTH = 30.0 * TIME_DAY private const val TIME_YEAR = 12.0 * TIME_MONTH diff --git a/AnkiDroid/src/main/res/values/01-core.xml b/AnkiDroid/src/main/res/values/01-core.xml index 414a22872a0a..c863c52eb9ac 100644 --- a/AnkiDroid/src/main/res/values/01-core.xml +++ b/AnkiDroid/src/main/res/values/01-core.xml @@ -111,6 +111,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted From de8aca2a7a124f6b674895e0322051fb6f649c7b Mon Sep 17 00:00:00 2001 From: AnkiDroid Translations Date: Mon, 10 Jun 2024 15:06:42 +0000 Subject: [PATCH 069/138] Updated strings from Crowdin --- AnkiDroid/src/main/res/values-af/01-core.xml | 1 + AnkiDroid/src/main/res/values-am/01-core.xml | 1 + AnkiDroid/src/main/res/values-ar/01-core.xml | 1 + AnkiDroid/src/main/res/values-az/01-core.xml | 1 + AnkiDroid/src/main/res/values-be/01-core.xml | 1 + AnkiDroid/src/main/res/values-bg/01-core.xml | 1 + AnkiDroid/src/main/res/values-bn/01-core.xml | 1 + AnkiDroid/src/main/res/values-ca/01-core.xml | 1 + AnkiDroid/src/main/res/values-ckb/01-core.xml | 1 + AnkiDroid/src/main/res/values-cs/01-core.xml | 1 + AnkiDroid/src/main/res/values-da/01-core.xml | 1 + AnkiDroid/src/main/res/values-de/01-core.xml | 1 + AnkiDroid/src/main/res/values-el/01-core.xml | 1 + AnkiDroid/src/main/res/values-eo/01-core.xml | 1 + AnkiDroid/src/main/res/values-es-rAR/01-core.xml | 1 + AnkiDroid/src/main/res/values-es-rES/01-core.xml | 1 + AnkiDroid/src/main/res/values-et/01-core.xml | 1 + AnkiDroid/src/main/res/values-eu/01-core.xml | 1 + AnkiDroid/src/main/res/values-fa/01-core.xml | 1 + AnkiDroid/src/main/res/values-fi/01-core.xml | 1 + AnkiDroid/src/main/res/values-fil/01-core.xml | 1 + AnkiDroid/src/main/res/values-fr/01-core.xml | 1 + AnkiDroid/src/main/res/values-fy/01-core.xml | 1 + AnkiDroid/src/main/res/values-ga/01-core.xml | 1 + AnkiDroid/src/main/res/values-gl/01-core.xml | 1 + AnkiDroid/src/main/res/values-got/01-core.xml | 1 + AnkiDroid/src/main/res/values-gu/01-core.xml | 1 + AnkiDroid/src/main/res/values-heb/01-core.xml | 1 + AnkiDroid/src/main/res/values-hi/01-core.xml | 1 + AnkiDroid/src/main/res/values-hr/01-core.xml | 1 + AnkiDroid/src/main/res/values-hu/01-core.xml | 1 + AnkiDroid/src/main/res/values-hy/01-core.xml | 1 + AnkiDroid/src/main/res/values-ind/01-core.xml | 1 + AnkiDroid/src/main/res/values-is/01-core.xml | 1 + AnkiDroid/src/main/res/values-it/01-core.xml | 1 + AnkiDroid/src/main/res/values-iw/01-core.xml | 1 + AnkiDroid/src/main/res/values-ja/01-core.xml | 1 + AnkiDroid/src/main/res/values-jv/01-core.xml | 1 + AnkiDroid/src/main/res/values-ka/01-core.xml | 1 + AnkiDroid/src/main/res/values-kk/01-core.xml | 1 + AnkiDroid/src/main/res/values-km/01-core.xml | 1 + AnkiDroid/src/main/res/values-kn/01-core.xml | 1 + AnkiDroid/src/main/res/values-ko/01-core.xml | 1 + AnkiDroid/src/main/res/values-ku/01-core.xml | 1 + AnkiDroid/src/main/res/values-ky/01-core.xml | 1 + AnkiDroid/src/main/res/values-lt/01-core.xml | 1 + AnkiDroid/src/main/res/values-lv/01-core.xml | 1 + AnkiDroid/src/main/res/values-mk/01-core.xml | 1 + AnkiDroid/src/main/res/values-ml/01-core.xml | 1 + AnkiDroid/src/main/res/values-mn/01-core.xml | 1 + AnkiDroid/src/main/res/values-mr/01-core.xml | 1 + AnkiDroid/src/main/res/values-ms/01-core.xml | 1 + AnkiDroid/src/main/res/values-my/01-core.xml | 1 + AnkiDroid/src/main/res/values-nl/01-core.xml | 1 + AnkiDroid/src/main/res/values-nn/01-core.xml | 1 + AnkiDroid/src/main/res/values-no/01-core.xml | 1 + AnkiDroid/src/main/res/values-or/01-core.xml | 1 + AnkiDroid/src/main/res/values-pa/01-core.xml | 1 + AnkiDroid/src/main/res/values-pl/01-core.xml | 1 + AnkiDroid/src/main/res/values-pt-rBR/01-core.xml | 1 + AnkiDroid/src/main/res/values-pt-rPT/01-core.xml | 1 + AnkiDroid/src/main/res/values-ro/01-core.xml | 1 + AnkiDroid/src/main/res/values-ru/01-core.xml | 1 + AnkiDroid/src/main/res/values-sat/01-core.xml | 1 + AnkiDroid/src/main/res/values-sc/01-core.xml | 1 + AnkiDroid/src/main/res/values-sk/01-core.xml | 1 + AnkiDroid/src/main/res/values-sl/01-core.xml | 1 + AnkiDroid/src/main/res/values-sq/01-core.xml | 1 + AnkiDroid/src/main/res/values-sr/01-core.xml | 1 + AnkiDroid/src/main/res/values-ss/01-core.xml | 1 + AnkiDroid/src/main/res/values-sv/01-core.xml | 1 + AnkiDroid/src/main/res/values-sw/01-core.xml | 1 + AnkiDroid/src/main/res/values-ta/01-core.xml | 1 + AnkiDroid/src/main/res/values-te/01-core.xml | 1 + AnkiDroid/src/main/res/values-tg/01-core.xml | 1 + AnkiDroid/src/main/res/values-tgl/01-core.xml | 1 + AnkiDroid/src/main/res/values-th/01-core.xml | 1 + AnkiDroid/src/main/res/values-ti/01-core.xml | 1 + AnkiDroid/src/main/res/values-tn/01-core.xml | 1 + AnkiDroid/src/main/res/values-tr/01-core.xml | 1 + AnkiDroid/src/main/res/values-ts/01-core.xml | 1 + AnkiDroid/src/main/res/values-tt/01-core.xml | 1 + AnkiDroid/src/main/res/values-uk/01-core.xml | 1 + AnkiDroid/src/main/res/values-ur/01-core.xml | 1 + AnkiDroid/src/main/res/values-uz/01-core.xml | 1 + AnkiDroid/src/main/res/values-ve/01-core.xml | 1 + AnkiDroid/src/main/res/values-vi/01-core.xml | 1 + AnkiDroid/src/main/res/values-wo/01-core.xml | 1 + AnkiDroid/src/main/res/values-xh/01-core.xml | 1 + AnkiDroid/src/main/res/values-yue/01-core.xml | 1 + AnkiDroid/src/main/res/values-zh-rCN/01-core.xml | 1 + AnkiDroid/src/main/res/values-zh-rTW/01-core.xml | 1 + AnkiDroid/src/main/res/values-zu/01-core.xml | 1 + 93 files changed, 93 insertions(+) diff --git a/AnkiDroid/src/main/res/values-af/01-core.xml b/AnkiDroid/src/main/res/values-af/01-core.xml index d15f8f7c376f..590f319aad0a 100644 --- a/AnkiDroid/src/main/res/values-af/01-core.xml +++ b/AnkiDroid/src/main/res/values-af/01-core.xml @@ -131,6 +131,7 @@ Pak Soek Ongeldige pak naam Congratulations! You have finished for now. + Deck finished for now! %s Geen kaarte is al verskulding nie Toestel bergplek is nie heg nie Sinkroniseer diff --git a/AnkiDroid/src/main/res/values-am/01-core.xml b/AnkiDroid/src/main/res/values-am/01-core.xml index 2a0dd54cb663..a7c4ad222d5c 100644 --- a/AnkiDroid/src/main/res/values-am/01-core.xml +++ b/AnkiDroid/src/main/res/values-am/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-ar/01-core.xml b/AnkiDroid/src/main/res/values-ar/01-core.xml index 96a9542694f1..9bed997008dc 100644 --- a/AnkiDroid/src/main/res/values-ar/01-core.xml +++ b/AnkiDroid/src/main/res/values-ar/01-core.xml @@ -143,6 +143,7 @@ بحث عن رزمة اسم رزمة غير صالح مبارك! أكملت مهامك الحالية. + Deck finished for now! %s لا توجد بطاقات مستحقة بعد لا توجد وحدة تخزين خارجية مزامنة diff --git a/AnkiDroid/src/main/res/values-az/01-core.xml b/AnkiDroid/src/main/res/values-az/01-core.xml index f4ee09406e1b..08f9ec909dec 100644 --- a/AnkiDroid/src/main/res/values-az/01-core.xml +++ b/AnkiDroid/src/main/res/values-az/01-core.xml @@ -131,6 +131,7 @@ Dəstə axtar Etibarsız kart adı Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Cihaz yaddaşı bağlı deyil Sinxronlaşdır diff --git a/AnkiDroid/src/main/res/values-be/01-core.xml b/AnkiDroid/src/main/res/values-be/01-core.xml index 762aa7d0c080..bd17d588d950 100644 --- a/AnkiDroid/src/main/res/values-be/01-core.xml +++ b/AnkiDroid/src/main/res/values-be/01-core.xml @@ -137,6 +137,7 @@ Пошук калоды Памылковая назва калоды Congratulations! You have finished for now. + Deck finished for now! %s На сёння картак не засталося. Картка памяці не падключаная Сінхранізаваць diff --git a/AnkiDroid/src/main/res/values-bg/01-core.xml b/AnkiDroid/src/main/res/values-bg/01-core.xml index c76559c6c3ee..006fcdfe7681 100644 --- a/AnkiDroid/src/main/res/values-bg/01-core.xml +++ b/AnkiDroid/src/main/res/values-bg/01-core.xml @@ -131,6 +131,7 @@ Потърси тесте Невалидно име на тесте Congratulations! You have finished for now. + Deck finished for now! %s Няма оставащи карти Не е поставена SD-карта памет Синхрон diff --git a/AnkiDroid/src/main/res/values-bn/01-core.xml b/AnkiDroid/src/main/res/values-bn/01-core.xml index 7c7caf53a76a..78c9641806eb 100644 --- a/AnkiDroid/src/main/res/values-bn/01-core.xml +++ b/AnkiDroid/src/main/res/values-bn/01-core.xml @@ -131,6 +131,7 @@ ডেক অনুসন্ধান ডেক নাম বৈধ নয় অভিনন্দন! আপাতত আপনার সমাপ্ত হয়েছে। + Deck finished for now! %s কোন কার্ড এখনও কার্যকরী হবে ডিভাইস স্টোরেজ মাউন্টেড নয় সিংক্রোনাইজ diff --git a/AnkiDroid/src/main/res/values-ca/01-core.xml b/AnkiDroid/src/main/res/values-ca/01-core.xml index d726512b1faf..72359707c0f5 100644 --- a/AnkiDroid/src/main/res/values-ca/01-core.xml +++ b/AnkiDroid/src/main/res/values-ca/01-core.xml @@ -131,6 +131,7 @@ Cerca un paquet El nom del paquet no és vàlid Enhorabona! Ja has acabat per ara. + Deck finished for now! %s No hi ha cartes previstes. La tarjeta SD no funciona correctament Sincronització diff --git a/AnkiDroid/src/main/res/values-ckb/01-core.xml b/AnkiDroid/src/main/res/values-ckb/01-core.xml index 01b4da7dd063..8cc7e2253159 100644 --- a/AnkiDroid/src/main/res/values-ckb/01-core.xml +++ b/AnkiDroid/src/main/res/values-ckb/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted هاوکاتگەری diff --git a/AnkiDroid/src/main/res/values-cs/01-core.xml b/AnkiDroid/src/main/res/values-cs/01-core.xml index d534378cccd2..850b8b4a6527 100644 --- a/AnkiDroid/src/main/res/values-cs/01-core.xml +++ b/AnkiDroid/src/main/res/values-cs/01-core.xml @@ -137,6 +137,7 @@ Hledat balíček Neplatný název balíčku Blahopřejeme! Prozatím máte hotovo. + Deck finished for now! %s Žádné karty ještě nejsou ke zkoušení Zařízení úložiště není připojeno Synchronizovat diff --git a/AnkiDroid/src/main/res/values-da/01-core.xml b/AnkiDroid/src/main/res/values-da/01-core.xml index a6511318fca3..5ad0c320a90f 100644 --- a/AnkiDroid/src/main/res/values-da/01-core.xml +++ b/AnkiDroid/src/main/res/values-da/01-core.xml @@ -131,6 +131,7 @@ Staksøgning Ugyldigt staknavn Tillykke! Du er færdig for denne gang. + Deck finished for now! %s Ingen kort i kø Enhedslagring er ikke tilkoblet Synkroniser diff --git a/AnkiDroid/src/main/res/values-de/01-core.xml b/AnkiDroid/src/main/res/values-de/01-core.xml index 9c9abf49bb5f..b94a5013b7b6 100644 --- a/AnkiDroid/src/main/res/values-de/01-core.xml +++ b/AnkiDroid/src/main/res/values-de/01-core.xml @@ -131,6 +131,7 @@ Stapelsuche Ungültiger Stapelname Glückwunsch! Das war alles für heute. + Deck finished for now! %s Es sind noch keine Karten fällig Gerätespeicher nicht eingebunden Synchronisieren diff --git a/AnkiDroid/src/main/res/values-el/01-core.xml b/AnkiDroid/src/main/res/values-el/01-core.xml index f9e2d20eee4d..fb10de6dc7f0 100644 --- a/AnkiDroid/src/main/res/values-el/01-core.xml +++ b/AnkiDroid/src/main/res/values-el/01-core.xml @@ -131,6 +131,7 @@ Αναζήτηση Μη έγκυρο όνομα Congratulations! You have finished for now. + Deck finished for now! %s Δεν υπάρχουν ακόμη κάρτες για επανάληψη O χώρος αποθήκευσης συσκευής δεν έχει προσαρτηθεί Συγχρονισμός diff --git a/AnkiDroid/src/main/res/values-eo/01-core.xml b/AnkiDroid/src/main/res/values-eo/01-core.xml index a92796087d67..01d14dc1c7a7 100644 --- a/AnkiDroid/src/main/res/values-eo/01-core.xml +++ b/AnkiDroid/src/main/res/values-eo/01-core.xml @@ -131,6 +131,7 @@ Serĉi kartaron Malĝusta nomo por kartaro Congratulations! You have finished for now. + Deck finished for now! %s Neniu karto por ripeti Aparata konservejo ne muntita Samtempigi diff --git a/AnkiDroid/src/main/res/values-es-rAR/01-core.xml b/AnkiDroid/src/main/res/values-es-rAR/01-core.xml index d669ead09af3..7bc4263c8622 100644 --- a/AnkiDroid/src/main/res/values-es-rAR/01-core.xml +++ b/AnkiDroid/src/main/res/values-es-rAR/01-core.xml @@ -131,6 +131,7 @@ Búsqueda de Mazo Nombre de mazo inválido ¡Enhorabuena! Has finalizado por ahora. + Deck finished for now! %s Aún no hay tarjetas programadas. El almacenamiento del dispositivo no se encuentra montado Sincronizar diff --git a/AnkiDroid/src/main/res/values-es-rES/01-core.xml b/AnkiDroid/src/main/res/values-es-rES/01-core.xml index 533025dcce50..a39dd4a9ac5a 100644 --- a/AnkiDroid/src/main/res/values-es-rES/01-core.xml +++ b/AnkiDroid/src/main/res/values-es-rES/01-core.xml @@ -131,6 +131,7 @@ Búsqueda de Mazo Nombre de mazo no válido ¡Enhorabuena! Has finalizado por ahora. + Deck finished for now! %s Todavía no hay ninguna tarjeta pendiente. Almacenamiento del dispositivo no montado Sincronizar diff --git a/AnkiDroid/src/main/res/values-et/01-core.xml b/AnkiDroid/src/main/res/values-et/01-core.xml index fdd328cef84b..a57b8a021a2a 100644 --- a/AnkiDroid/src/main/res/values-et/01-core.xml +++ b/AnkiDroid/src/main/res/values-et/01-core.xml @@ -131,6 +131,7 @@ Otsi kaardipakki Vigane kaardipaki nimi Congratulations! You have finished for now. + Deck finished for now! %s Veel pole kaart ootel Seadme mälu pole paigaldatud Sünkrooni diff --git a/AnkiDroid/src/main/res/values-eu/01-core.xml b/AnkiDroid/src/main/res/values-eu/01-core.xml index b517633c7d0f..c32920eb0ed7 100644 --- a/AnkiDroid/src/main/res/values-eu/01-core.xml +++ b/AnkiDroid/src/main/res/values-eu/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sinkronizatu diff --git a/AnkiDroid/src/main/res/values-fa/01-core.xml b/AnkiDroid/src/main/res/values-fa/01-core.xml index 49b0469a6093..dbf465da3f2c 100644 --- a/AnkiDroid/src/main/res/values-fa/01-core.xml +++ b/AnkiDroid/src/main/res/values-fa/01-core.xml @@ -131,6 +131,7 @@ جستجوی دسته‌ها نام دسته نامعتبر است Congratulations! You have finished for now. + Deck finished for now! %s هیچ کارتی هنوز موعد نیست حافظۀ دستگاه یافت نشد همگام سازی diff --git a/AnkiDroid/src/main/res/values-fi/01-core.xml b/AnkiDroid/src/main/res/values-fi/01-core.xml index 808a61503464..c9f5a62a8a7d 100644 --- a/AnkiDroid/src/main/res/values-fi/01-core.xml +++ b/AnkiDroid/src/main/res/values-fi/01-core.xml @@ -131,6 +131,7 @@ Hae pakkaa Virheellinen pakan nimi Congratulations! You have finished for now. + Deck finished for now! %s Kortteja ei tarvitse vielä kerrata Laitteen tallennustilaa ei ole kiinnitetty Synkronoi diff --git a/AnkiDroid/src/main/res/values-fil/01-core.xml b/AnkiDroid/src/main/res/values-fil/01-core.xml index cee1ecdf68c6..5dc6f743ef4c 100644 --- a/AnkiDroid/src/main/res/values-fil/01-core.xml +++ b/AnkiDroid/src/main/res/values-fil/01-core.xml @@ -131,6 +131,7 @@ Maghanap ng Deck Hindi wasto ang pangalan ng deck Binabati kita! Natapos mo na sa ngayon. + Deck finished for now! %s Wala pang card na nakatakda Ang device storage ay hindi naka-mount I-sync diff --git a/AnkiDroid/src/main/res/values-fr/01-core.xml b/AnkiDroid/src/main/res/values-fr/01-core.xml index cadead758706..662de7d033ad 100644 --- a/AnkiDroid/src/main/res/values-fr/01-core.xml +++ b/AnkiDroid/src/main/res/values-fr/01-core.xml @@ -131,6 +131,7 @@ Chercher un deck Nom de paquet invalide Félicitations ! Vous avez terminé… pour l’instant ! + Deck finished for now! %s Aucune carte due actuellement Aucune carte SD Synchroniser diff --git a/AnkiDroid/src/main/res/values-fy/01-core.xml b/AnkiDroid/src/main/res/values-fy/01-core.xml index f3896ea0e5cf..300700906895 100644 --- a/AnkiDroid/src/main/res/values-fy/01-core.xml +++ b/AnkiDroid/src/main/res/values-fy/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-ga/01-core.xml b/AnkiDroid/src/main/res/values-ga/01-core.xml index ec572f4b5f17..11024e3217f1 100644 --- a/AnkiDroid/src/main/res/values-ga/01-core.xml +++ b/AnkiDroid/src/main/res/values-ga/01-core.xml @@ -140,6 +140,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-gl/01-core.xml b/AnkiDroid/src/main/res/values-gl/01-core.xml index 6f23480269c7..743c6bf9e15e 100644 --- a/AnkiDroid/src/main/res/values-gl/01-core.xml +++ b/AnkiDroid/src/main/res/values-gl/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s Aínda non hai cartóns pendentes Almacenamento do dispositivo non montado Sincronizar diff --git a/AnkiDroid/src/main/res/values-got/01-core.xml b/AnkiDroid/src/main/res/values-got/01-core.xml index 98ab3a7b758f..c33dff2c0af2 100644 --- a/AnkiDroid/src/main/res/values-got/01-core.xml +++ b/AnkiDroid/src/main/res/values-got/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s Ni karta binah gakiusan. Device storage not mounted Galeik diff --git a/AnkiDroid/src/main/res/values-gu/01-core.xml b/AnkiDroid/src/main/res/values-gu/01-core.xml index c9470d9c2500..89602dcdc24b 100644 --- a/AnkiDroid/src/main/res/values-gu/01-core.xml +++ b/AnkiDroid/src/main/res/values-gu/01-core.xml @@ -131,6 +131,7 @@ ડેક શોધ અમાન્ય ડેક નામ અભિનંદન! તમે હમણાં માટે સમાપ્ત કર્યું છે. + Deck finished for now! %s હજુ સુધી કોઈ કાર્ડ બાકી નથી ઉપકરણ સંગ્રહ માઉન્ટ થયેલ નથી સમન્વયન diff --git a/AnkiDroid/src/main/res/values-heb/01-core.xml b/AnkiDroid/src/main/res/values-heb/01-core.xml index 09333bf0f5bf..dc0824fa07fc 100644 --- a/AnkiDroid/src/main/res/values-heb/01-core.xml +++ b/AnkiDroid/src/main/res/values-heb/01-core.xml @@ -138,6 +138,7 @@ חיפוש חפיסה שם חפיסה לא חוקי אשריך! סיימת לעת עתה. + Deck finished for now! %s אין כרטיסים נוספים התקן אחסון לא מחובר סנכרון diff --git a/AnkiDroid/src/main/res/values-hi/01-core.xml b/AnkiDroid/src/main/res/values-hi/01-core.xml index 16d91274de0c..9b5ca9d62d17 100644 --- a/AnkiDroid/src/main/res/values-hi/01-core.xml +++ b/AnkiDroid/src/main/res/values-hi/01-core.xml @@ -131,6 +131,7 @@ डेक खोज अमान्य डेक नाम बधाई हो! आपने अभी के लिए समाप्त कर लिया है. + Deck finished for now! %s कोई कार्ड अभी तक देय नहीं है डिवाइस संग्रह माउंट नहीं सिंक diff --git a/AnkiDroid/src/main/res/values-hr/01-core.xml b/AnkiDroid/src/main/res/values-hr/01-core.xml index 42994e42e884..b8c274453680 100644 --- a/AnkiDroid/src/main/res/values-hr/01-core.xml +++ b/AnkiDroid/src/main/res/values-hr/01-core.xml @@ -134,6 +134,7 @@ Deck Search Invalid deck name Čestitamo! Za sada ste završili. + Deck finished for now! %s Još nije potrebno dovršiti ni jednu karticu Pohrana uređaja nije montirana Sinkroniziraj diff --git a/AnkiDroid/src/main/res/values-hu/01-core.xml b/AnkiDroid/src/main/res/values-hu/01-core.xml index 4d781fa7ea6a..fad6d8f75747 100644 --- a/AnkiDroid/src/main/res/values-hu/01-core.xml +++ b/AnkiDroid/src/main/res/values-hu/01-core.xml @@ -131,6 +131,7 @@ Paklik keresése Érvénytelen paklinév Congratulations! You have finished for now. + Deck finished for now! %s Jelenleg nincs esedékes kártya Nincs elérhető tárolóhely Szinkronizálás diff --git a/AnkiDroid/src/main/res/values-hy/01-core.xml b/AnkiDroid/src/main/res/values-hy/01-core.xml index 8261e95db145..aabdb2c5eaae 100644 --- a/AnkiDroid/src/main/res/values-hy/01-core.xml +++ b/AnkiDroid/src/main/res/values-hy/01-core.xml @@ -131,6 +131,7 @@ Կապուկների որոնում Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s Կրկնելիք քարտեր դեռ չկան Սարքի պահեստը տեղադրված չէ Համաժամեցում diff --git a/AnkiDroid/src/main/res/values-ind/01-core.xml b/AnkiDroid/src/main/res/values-ind/01-core.xml index f886a20ae076..4bb47aceb0a5 100644 --- a/AnkiDroid/src/main/res/values-ind/01-core.xml +++ b/AnkiDroid/src/main/res/values-ind/01-core.xml @@ -128,6 +128,7 @@ Pencarian Dek Nama dek tidak valid Congratulations! You have finished for now. + Deck finished for now! %s Belum ada kartu jatuh tempo. Penyimpanan perangkat tidak terpasang Sinkronisasi diff --git a/AnkiDroid/src/main/res/values-is/01-core.xml b/AnkiDroid/src/main/res/values-is/01-core.xml index 8bc574242c05..3247aa9565a7 100644 --- a/AnkiDroid/src/main/res/values-is/01-core.xml +++ b/AnkiDroid/src/main/res/values-is/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-it/01-core.xml b/AnkiDroid/src/main/res/values-it/01-core.xml index 25510604ce7d..391f9760c59d 100644 --- a/AnkiDroid/src/main/res/values-it/01-core.xml +++ b/AnkiDroid/src/main/res/values-it/01-core.xml @@ -131,6 +131,7 @@ Ricerca mazzo Nome mazzo non valido Congratulazioni! Hai finito per ora. + Deck finished for now! %s Nessuna carta da ripetere ora. Dispositivo archiviazione non montato Sincronizza diff --git a/AnkiDroid/src/main/res/values-iw/01-core.xml b/AnkiDroid/src/main/res/values-iw/01-core.xml index 09333bf0f5bf..dc0824fa07fc 100644 --- a/AnkiDroid/src/main/res/values-iw/01-core.xml +++ b/AnkiDroid/src/main/res/values-iw/01-core.xml @@ -138,6 +138,7 @@ חיפוש חפיסה שם חפיסה לא חוקי אשריך! סיימת לעת עתה. + Deck finished for now! %s אין כרטיסים נוספים התקן אחסון לא מחובר סנכרון diff --git a/AnkiDroid/src/main/res/values-ja/01-core.xml b/AnkiDroid/src/main/res/values-ja/01-core.xml index 6769342e7f86..3a3f5a904a1a 100644 --- a/AnkiDroid/src/main/res/values-ja/01-core.xml +++ b/AnkiDroid/src/main/res/values-ja/01-core.xml @@ -128,6 +128,7 @@ デッキを検索 無効なデッキ名です おめでとうございます! このデッキの現在の課題をすべて達成しました! + Deck finished for now! %s このデッキの今日の課題はまだ残っていますが、どれもまだ学習予定時刻に達していません デバイスのストレージがマウントされていません 同期 diff --git a/AnkiDroid/src/main/res/values-jv/01-core.xml b/AnkiDroid/src/main/res/values-jv/01-core.xml index 14f075f1926f..637cb25a7de5 100644 --- a/AnkiDroid/src/main/res/values-jv/01-core.xml +++ b/AnkiDroid/src/main/res/values-jv/01-core.xml @@ -128,6 +128,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-ka/01-core.xml b/AnkiDroid/src/main/res/values-ka/01-core.xml index 557dcd630fcb..e062eef8e5c1 100644 --- a/AnkiDroid/src/main/res/values-ka/01-core.xml +++ b/AnkiDroid/src/main/res/values-ka/01-core.xml @@ -131,6 +131,7 @@ დასტის ძიება დასტის სახელი არასწორია გილოცავთ! დღეისთვის სულ ეს იყო. + Deck finished for now! %s ჯერ ბარათები არ არის მოწყობილობის მეხსიერება არაა ჩაყენებული სინქრონიზაცია diff --git a/AnkiDroid/src/main/res/values-kk/01-core.xml b/AnkiDroid/src/main/res/values-kk/01-core.xml index 4d8415dff6d3..78823cdc542f 100644 --- a/AnkiDroid/src/main/res/values-kk/01-core.xml +++ b/AnkiDroid/src/main/res/values-kk/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-km/01-core.xml b/AnkiDroid/src/main/res/values-km/01-core.xml index df732364aa1f..588304dfd43a 100644 --- a/AnkiDroid/src/main/res/values-km/01-core.xml +++ b/AnkiDroid/src/main/res/values-km/01-core.xml @@ -128,6 +128,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-kn/01-core.xml b/AnkiDroid/src/main/res/values-kn/01-core.xml index fecc22b56040..40d1f2b13b29 100644 --- a/AnkiDroid/src/main/res/values-kn/01-core.xml +++ b/AnkiDroid/src/main/res/values-kn/01-core.xml @@ -131,6 +131,7 @@ ಡೆಕ್ ಹುಡುಕಾಟ ಅಮಾನ್ಯ ಡೆಕ್ ಹೆಸರು ಅಭಿನಂದನೆಗಳು! ನೀವು ಸದ್ಯಕ್ಕೆ ಮುಗಿಸಿದ್ದೀರಿ. + Deck finished for now! %s ಯಾವುದೇ ಕಾರ್ಡ್‌ಗಳು ಇನ್ನೂ ಬಾಕಿ ಉಳಿದಿಲ್ಲ ಸಾಧನ ಸಂಗ್ರಹಣೆಯನ್ನು ಆರೋಹಿಸಲಾಗಿಲ್ಲ ಸಿಂಕ್ diff --git a/AnkiDroid/src/main/res/values-ko/01-core.xml b/AnkiDroid/src/main/res/values-ko/01-core.xml index 8e5b56a9a0e0..d55e6cea2a5a 100644 --- a/AnkiDroid/src/main/res/values-ko/01-core.xml +++ b/AnkiDroid/src/main/res/values-ko/01-core.xml @@ -128,6 +128,7 @@ 뭉치 검색 유효하지 않은 뭉치 이름입니다 Congratulations! You have finished for now. + Deck finished for now! %s 남은 카드가 없습니다. 장치 저장소가 마운트되지 않음 동기화 diff --git a/AnkiDroid/src/main/res/values-ku/01-core.xml b/AnkiDroid/src/main/res/values-ku/01-core.xml index 19afcac2b6a5..df9e32d6d02d 100644 --- a/AnkiDroid/src/main/res/values-ku/01-core.xml +++ b/AnkiDroid/src/main/res/values-ku/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-ky/01-core.xml b/AnkiDroid/src/main/res/values-ky/01-core.xml index d1a7f2f7f5da..c81d73f3ec4d 100644 --- a/AnkiDroid/src/main/res/values-ky/01-core.xml +++ b/AnkiDroid/src/main/res/values-ky/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-lt/01-core.xml b/AnkiDroid/src/main/res/values-lt/01-core.xml index 41056d09e401..934a7489b324 100644 --- a/AnkiDroid/src/main/res/values-lt/01-core.xml +++ b/AnkiDroid/src/main/res/values-lt/01-core.xml @@ -137,6 +137,7 @@ Rinkinio paieška Blogas rinkinio vardas Congratulations! You have finished for now. + Deck finished for now! %s Numatytų kortelių kol kas dar nėra Atminties įrenginys neprijungtas Sinchronizuoti diff --git a/AnkiDroid/src/main/res/values-lv/01-core.xml b/AnkiDroid/src/main/res/values-lv/01-core.xml index b10afa98472b..9cee85e8e0d4 100644 --- a/AnkiDroid/src/main/res/values-lv/01-core.xml +++ b/AnkiDroid/src/main/res/values-lv/01-core.xml @@ -134,6 +134,7 @@ Kavu meklētājs Nederīgs kavas nosaukums Congratulations! You have finished for now. + Deck finished for now! %s Nav gaidāmu kāršu Ierīces krātuve nav uzstādīta Saskaņošana diff --git a/AnkiDroid/src/main/res/values-mk/01-core.xml b/AnkiDroid/src/main/res/values-mk/01-core.xml index 5b9b7a4543c3..bd4dc7d1b302 100644 --- a/AnkiDroid/src/main/res/values-mk/01-core.xml +++ b/AnkiDroid/src/main/res/values-mk/01-core.xml @@ -131,6 +131,7 @@ Deck Search Невалидно име за шпил Congratulations! You have finished for now. + Deck finished for now! %s Ниедна картичка не е доспеана Уредот за складирање не е монтиран Синхронизирај diff --git a/AnkiDroid/src/main/res/values-ml/01-core.xml b/AnkiDroid/src/main/res/values-ml/01-core.xml index bfa89fddab0a..70ff589ba061 100644 --- a/AnkiDroid/src/main/res/values-ml/01-core.xml +++ b/AnkiDroid/src/main/res/values-ml/01-core.xml @@ -131,6 +131,7 @@ Deck Search ഡെക്കിന്റെ പേര് അസാധുവാണ് Congratulations! You have finished for now. + Deck finished for now! %s കാർഡുകളൊന്നും ഇതുവരെ ലഭിച്ചിട്ടില്ല ഉപകരണ സംഭരണം മ .ണ്ട് ചെയ്തിട്ടില്ല സമന്വയിപ്പിക്കുക diff --git a/AnkiDroid/src/main/res/values-mn/01-core.xml b/AnkiDroid/src/main/res/values-mn/01-core.xml index aa4b81831c5e..f7e50bb8c272 100644 --- a/AnkiDroid/src/main/res/values-mn/01-core.xml +++ b/AnkiDroid/src/main/res/values-mn/01-core.xml @@ -131,6 +131,7 @@ Интернетээс багц хайх Ингэж нэрлэх боломжгүй байна Congratulations! You have finished for now. + Deck finished for now! %s Одоохондоо сурах, давтах карт алга байна Багтаамжийн хэрэгсэл холбогдоогүй байна Зэрэгцүүлэх diff --git a/AnkiDroid/src/main/res/values-mr/01-core.xml b/AnkiDroid/src/main/res/values-mr/01-core.xml index 4bbe3ecd9c39..1066a6fe3e19 100644 --- a/AnkiDroid/src/main/res/values-mr/01-core.xml +++ b/AnkiDroid/src/main/res/values-mr/01-core.xml @@ -131,6 +131,7 @@ डेक शोध अवैध डेक नाव अभिनंदन! तुम्ही आतासाठी पूर्ण केले आहे. + Deck finished for now! %s अद्याप कोणतीही कार्ड शिल्लक नाही डिव्हाइस संचयन आरोहित नाही समक्रमित करा diff --git a/AnkiDroid/src/main/res/values-ms/01-core.xml b/AnkiDroid/src/main/res/values-ms/01-core.xml index c7b92101fef9..a5d1d8bb38ed 100644 --- a/AnkiDroid/src/main/res/values-ms/01-core.xml +++ b/AnkiDroid/src/main/res/values-ms/01-core.xml @@ -128,6 +128,7 @@ Carian Dek Nama dek tidak sah Congratulations! You have finished for now. + Deck finished for now! %s Tiada kad tertunggak lagi Peranti storan tidak dipasang Segerak diff --git a/AnkiDroid/src/main/res/values-my/01-core.xml b/AnkiDroid/src/main/res/values-my/01-core.xml index ee3de2211143..cbb2b92d7919 100644 --- a/AnkiDroid/src/main/res/values-my/01-core.xml +++ b/AnkiDroid/src/main/res/values-my/01-core.xml @@ -133,6 +133,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-nl/01-core.xml b/AnkiDroid/src/main/res/values-nl/01-core.xml index 56cc917ed62a..46e1986abe51 100644 --- a/AnkiDroid/src/main/res/values-nl/01-core.xml +++ b/AnkiDroid/src/main/res/values-nl/01-core.xml @@ -131,6 +131,7 @@ Set doorzoeken Ongeldige setnaam Congratulations! You have finished for now. + Deck finished for now! %s Nog geen kaarten te doen. Apparaatopslag niet aangesloten Synchroniseer diff --git a/AnkiDroid/src/main/res/values-nn/01-core.xml b/AnkiDroid/src/main/res/values-nn/01-core.xml index 2007f7999933..350227e3ad6d 100644 --- a/AnkiDroid/src/main/res/values-nn/01-core.xml +++ b/AnkiDroid/src/main/res/values-nn/01-core.xml @@ -131,6 +131,7 @@ Finn kortstokk Ugildt namn på kortleik Congratulations! You have finished for now. + Deck finished for now! %s Ingen kort forfaller ennå Device storage not mounted Synkroniser diff --git a/AnkiDroid/src/main/res/values-no/01-core.xml b/AnkiDroid/src/main/res/values-no/01-core.xml index 3a16b27bf405..488e3f9962ff 100644 --- a/AnkiDroid/src/main/res/values-no/01-core.xml +++ b/AnkiDroid/src/main/res/values-no/01-core.xml @@ -131,6 +131,7 @@ Finn kortstokk Ugyldig navn Congratulations! You have finished for now. + Deck finished for now! %s Ingen kort forfaller ennå Device storage not mounted Synkroniser diff --git a/AnkiDroid/src/main/res/values-or/01-core.xml b/AnkiDroid/src/main/res/values-or/01-core.xml index 7d0283397a5a..da42a9801acc 100644 --- a/AnkiDroid/src/main/res/values-or/01-core.xml +++ b/AnkiDroid/src/main/res/values-or/01-core.xml @@ -131,6 +131,7 @@ ତାସଖଣ୍ଡ ସନ୍ଧାନ ଅବୈଧ ତାସଖଣ୍ଡ ନାମ Congratulations! You have finished for now. + Deck finished for now! %s କୌଣସି ପତ୍ର ବାକି ନାହିଁ ଡିଵାଇସ୍ ଷ୍ଟୋରେଜ୍ ଭର୍ତ୍ତି କରାଯାଇ ନାହିଁ ସୀଙ୍କ୍ diff --git a/AnkiDroid/src/main/res/values-pa/01-core.xml b/AnkiDroid/src/main/res/values-pa/01-core.xml index 42a6bfd7b151..24f775cc6faa 100644 --- a/AnkiDroid/src/main/res/values-pa/01-core.xml +++ b/AnkiDroid/src/main/res/values-pa/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-pl/01-core.xml b/AnkiDroid/src/main/res/values-pl/01-core.xml index 4276053427b9..9bd6b423c256 100644 --- a/AnkiDroid/src/main/res/values-pl/01-core.xml +++ b/AnkiDroid/src/main/res/values-pl/01-core.xml @@ -137,6 +137,7 @@ Wyszukiwanie talii Nieprawidłowa nazwa talii Gratulacje! Zakończono powtórki na dziś. + Deck finished for now! %s Nie ma żadnych kart do przejrzenia. Urządzenie pamięci masowej nie zostało zamontowane Synchronizuj diff --git a/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml b/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml index 69a9f28c2e94..0be075ad1215 100644 --- a/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml +++ b/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml @@ -131,6 +131,7 @@ Pesquisar baralho Nome do baralho inválido Parabéns! Você terminou por enquanto. + Deck finished for now! %s Sem cartões programados por enquanto. Armazenamento do dispositivo não montado Sincronizar diff --git a/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml b/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml index 620df44d834d..1702aaaa3faf 100644 --- a/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml +++ b/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml @@ -131,6 +131,7 @@ Pesquisar baralhos Nome de baralho inválido Parabéns! Terminou por agora. + Deck finished for now! %s Nenhuma ficha por rever Armazenamento do dispositivo não montado Sincronizar diff --git a/AnkiDroid/src/main/res/values-ro/01-core.xml b/AnkiDroid/src/main/res/values-ro/01-core.xml index facd74d98a44..fc53be66e23d 100644 --- a/AnkiDroid/src/main/res/values-ro/01-core.xml +++ b/AnkiDroid/src/main/res/values-ro/01-core.xml @@ -134,6 +134,7 @@ Căutare Pachete Nume pachet invalid Congratulations! You have finished for now. + Deck finished for now! %s Niciun cartonaș scadent Cardul SD nu a fost găsit Sincronizare diff --git a/AnkiDroid/src/main/res/values-ru/01-core.xml b/AnkiDroid/src/main/res/values-ru/01-core.xml index f6b535381cfd..2a72a1a9b0c9 100644 --- a/AnkiDroid/src/main/res/values-ru/01-core.xml +++ b/AnkiDroid/src/main/res/values-ru/01-core.xml @@ -137,6 +137,7 @@ Поиск колоды Недопустимое название колоды Congratulations! You have finished for now. + Deck finished for now! %s Нет карточек на сегодня Карта памяти не установлена Синхронизировать diff --git a/AnkiDroid/src/main/res/values-sat/01-core.xml b/AnkiDroid/src/main/res/values-sat/01-core.xml index 2f3df5414d9d..023caf3aed77 100644 --- a/AnkiDroid/src/main/res/values-sat/01-core.xml +++ b/AnkiDroid/src/main/res/values-sat/01-core.xml @@ -131,6 +131,7 @@ ᱰᱮᱠ ᱥᱮᱸᱫᱽᱨᱟ ᱰᱮᱠ ᱧᱩᱛᱩᱢ ᱵᱷᱩᱞ Congratulations! You have finished for now. + Deck finished for now! %s ᱱᱤᱛᱚᱜ ᱫᱚ ᱠᱟᱰ ᱵᱟᱹᱱᱩᱜᱼᱟ ᱥᱟᱫᱷᱚᱱ ᱜᱚᱫᱟᱢ ᱫᱚ ᱵᱟᱭ ᱢᱟᱩᱱᱴ ᱟᱠᱟᱱᱟ ᱟᱭᱩᱨ ᱢᱤᱫ diff --git a/AnkiDroid/src/main/res/values-sc/01-core.xml b/AnkiDroid/src/main/res/values-sc/01-core.xml index b68cb291e53e..bd235164c666 100644 --- a/AnkiDroid/src/main/res/values-sc/01-core.xml +++ b/AnkiDroid/src/main/res/values-sc/01-core.xml @@ -133,6 +133,7 @@ Chirca de matzos Nùmene de su matzu non vàlidu Congratulations! You have finished for now. + Deck finished for now! %s Peruna carta de revisionare como Sa memòria de su dispositivu no est montada Sincroniza diff --git a/AnkiDroid/src/main/res/values-sk/01-core.xml b/AnkiDroid/src/main/res/values-sk/01-core.xml index 117df5f3665b..6759fd81e033 100644 --- a/AnkiDroid/src/main/res/values-sk/01-core.xml +++ b/AnkiDroid/src/main/res/values-sk/01-core.xml @@ -137,6 +137,7 @@ Vyhľadávanie v balíčku Neplatný názov balíčka Blahoželáme! Na teraz ste tento balíček dokončili. + Deck finished for now! %s Ešte nie sú žiadne kartičky na preskúšanie Ukladacie zariadenie nepripojené Synchronizácia diff --git a/AnkiDroid/src/main/res/values-sl/01-core.xml b/AnkiDroid/src/main/res/values-sl/01-core.xml index 8c882d3c6da3..684e3face736 100644 --- a/AnkiDroid/src/main/res/values-sl/01-core.xml +++ b/AnkiDroid/src/main/res/values-sl/01-core.xml @@ -137,6 +137,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s Nobena kartica še ni zapadla Pomnilniška naprava ni priklopljena Sinhroniziraj diff --git a/AnkiDroid/src/main/res/values-sq/01-core.xml b/AnkiDroid/src/main/res/values-sq/01-core.xml index bf0af94a58a3..506d5133ea6c 100644 --- a/AnkiDroid/src/main/res/values-sq/01-core.xml +++ b/AnkiDroid/src/main/res/values-sq/01-core.xml @@ -131,6 +131,7 @@ Kërkimi i kuvertës Emër i pavlefshëm kuvertë urime! Ju keni mbaruar tani për tani. + Deck finished for now! %s Nuk ka ende afat Hapësira ruajtëse e pajisjes nuk është montuar Sinkronizo diff --git a/AnkiDroid/src/main/res/values-sr/01-core.xml b/AnkiDroid/src/main/res/values-sr/01-core.xml index 8234db214d16..3e8e2251f22a 100644 --- a/AnkiDroid/src/main/res/values-sr/01-core.xml +++ b/AnkiDroid/src/main/res/values-sr/01-core.xml @@ -134,6 +134,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s Нема редне карте. Уређај за чување није монтиран Синхронизујте diff --git a/AnkiDroid/src/main/res/values-ss/01-core.xml b/AnkiDroid/src/main/res/values-ss/01-core.xml index 2a0dd54cb663..a7c4ad222d5c 100644 --- a/AnkiDroid/src/main/res/values-ss/01-core.xml +++ b/AnkiDroid/src/main/res/values-ss/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-sv/01-core.xml b/AnkiDroid/src/main/res/values-sv/01-core.xml index 61888602e5c9..d412633b29ee 100644 --- a/AnkiDroid/src/main/res/values-sv/01-core.xml +++ b/AnkiDroid/src/main/res/values-sv/01-core.xml @@ -131,6 +131,7 @@ Kortlekssökning Ogiltigt kortleksnamn Grattis! Du är klar för stunden. + Deck finished for now! %s Inga kort i kö. Lagringsenhet ej monterad Synkronisera diff --git a/AnkiDroid/src/main/res/values-sw/01-core.xml b/AnkiDroid/src/main/res/values-sw/01-core.xml index 2a0dd54cb663..a7c4ad222d5c 100644 --- a/AnkiDroid/src/main/res/values-sw/01-core.xml +++ b/AnkiDroid/src/main/res/values-sw/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-ta/01-core.xml b/AnkiDroid/src/main/res/values-ta/01-core.xml index b5a354a0f450..cb8cbbf2bde1 100644 --- a/AnkiDroid/src/main/res/values-ta/01-core.xml +++ b/AnkiDroid/src/main/res/values-ta/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s இல்லை அட்டைகள் இன்னும் காரணமாக உள்ளன சாதன சேமிப்பகம் பொருத்தப்படவில்லை ஒத்திசைக்க diff --git a/AnkiDroid/src/main/res/values-te/01-core.xml b/AnkiDroid/src/main/res/values-te/01-core.xml index 5ebec6b6e747..881a37333afb 100644 --- a/AnkiDroid/src/main/res/values-te/01-core.xml +++ b/AnkiDroid/src/main/res/values-te/01-core.xml @@ -131,6 +131,7 @@ డెక్ శోధన చెల్లని డెక్ పేరు అభినందనలు! ప్రస్తుతానికి మీరు పూర్తి చేసారు. + Deck finished for now! %s ఎక్కువ కార్డులు లేవు పరికర నిల్వ మౌంట్ చేయబడలేదు సమకాలీకరణ diff --git a/AnkiDroid/src/main/res/values-tg/01-core.xml b/AnkiDroid/src/main/res/values-tg/01-core.xml index 9d4321d6c35e..c1ddca0341cc 100644 --- a/AnkiDroid/src/main/res/values-tg/01-core.xml +++ b/AnkiDroid/src/main/res/values-tg/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-tgl/01-core.xml b/AnkiDroid/src/main/res/values-tgl/01-core.xml index 4f52602d93ad..b24c1dde5a08 100644 --- a/AnkiDroid/src/main/res/values-tgl/01-core.xml +++ b/AnkiDroid/src/main/res/values-tgl/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s Wala pang barahang kailangan Hindi nakamount ang storage ng aparato I-singkronisa diff --git a/AnkiDroid/src/main/res/values-th/01-core.xml b/AnkiDroid/src/main/res/values-th/01-core.xml index 0bc87f7d83ea..26ec2c0cf727 100644 --- a/AnkiDroid/src/main/res/values-th/01-core.xml +++ b/AnkiDroid/src/main/res/values-th/01-core.xml @@ -128,6 +128,7 @@ ค้นหาสำรับ ชื่อนี้ไม่สามารถตั้งให้สำรับได้ ยินดีด้วย! คุณทบทวนเสร็จแล้วสำหรับตอนนี้ + Deck finished for now! %s ไม่มีบัตรคำที่ต้องทบทวนในตอนนี้ Device storage not mounted การซิงค์ diff --git a/AnkiDroid/src/main/res/values-ti/01-core.xml b/AnkiDroid/src/main/res/values-ti/01-core.xml index ffd5a919dcc2..7699be916aaf 100644 --- a/AnkiDroid/src/main/res/values-ti/01-core.xml +++ b/AnkiDroid/src/main/res/values-ti/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s ክሳብ ሕጂ ዝተገብኡ ካርድታ የለውን ናይ መባይል ቦታ ኣይተጻዕነን ኣሎ። ምውህሃድ diff --git a/AnkiDroid/src/main/res/values-tn/01-core.xml b/AnkiDroid/src/main/res/values-tn/01-core.xml index 2a0dd54cb663..a7c4ad222d5c 100644 --- a/AnkiDroid/src/main/res/values-tn/01-core.xml +++ b/AnkiDroid/src/main/res/values-tn/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-tr/01-core.xml b/AnkiDroid/src/main/res/values-tr/01-core.xml index d95e415e4ee9..a464713a7063 100644 --- a/AnkiDroid/src/main/res/values-tr/01-core.xml +++ b/AnkiDroid/src/main/res/values-tr/01-core.xml @@ -131,6 +131,7 @@ Deste Ara Geçersiz deste adı Tebrikler! Şimdilik bitirdiniz. + Deck finished for now! %s Henüz sırası gelmiş kart yok Cihaz hafızası takılı değil Senkronize et diff --git a/AnkiDroid/src/main/res/values-ts/01-core.xml b/AnkiDroid/src/main/res/values-ts/01-core.xml index 2a0dd54cb663..a7c4ad222d5c 100644 --- a/AnkiDroid/src/main/res/values-ts/01-core.xml +++ b/AnkiDroid/src/main/res/values-ts/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-tt/01-core.xml b/AnkiDroid/src/main/res/values-tt/01-core.xml index 6d8b076a2391..5cf2174ad971 100644 --- a/AnkiDroid/src/main/res/values-tt/01-core.xml +++ b/AnkiDroid/src/main/res/values-tt/01-core.xml @@ -128,6 +128,7 @@ Колода эзләү Шундый колода исеме була алмый Congratulations! You have finished for now. + Deck finished for now! %s Хәзерге вакытка кәртләр юк Хәтер картасы куелмаган Синхронизацияләргә diff --git a/AnkiDroid/src/main/res/values-uk/01-core.xml b/AnkiDroid/src/main/res/values-uk/01-core.xml index cb74739dedd4..dc90483a424d 100644 --- a/AnkiDroid/src/main/res/values-uk/01-core.xml +++ b/AnkiDroid/src/main/res/values-uk/01-core.xml @@ -137,6 +137,7 @@ Пошук колоди Некоректна назва колоди Вітаємо! На разі це все. + Deck finished for now! %s Не залишилось карток на перегляд Пристрій зберігання не підключено Синхронізувати diff --git a/AnkiDroid/src/main/res/values-ur/01-core.xml b/AnkiDroid/src/main/res/values-ur/01-core.xml index b828877a7b48..c82501d93068 100644 --- a/AnkiDroid/src/main/res/values-ur/01-core.xml +++ b/AnkiDroid/src/main/res/values-ur/01-core.xml @@ -131,6 +131,7 @@ ڈیک تلاش ڈیک کا نام غلط ہے Congratulations! You have finished for now. + Deck finished for now! %s ابھی تک کوئی کارڈ باقی نہیں ہے ڈیوائس اسٹوریج نصب نہیں ہے ہم وقت سازی diff --git a/AnkiDroid/src/main/res/values-uz/01-core.xml b/AnkiDroid/src/main/res/values-uz/01-core.xml index b92b47184c5e..c358b9802da8 100644 --- a/AnkiDroid/src/main/res/values-uz/01-core.xml +++ b/AnkiDroid/src/main/res/values-uz/01-core.xml @@ -131,6 +131,7 @@ To\'plam qidirish To\'plamning nomi yaroqsiz Congratulations! You have finished for now. + Deck finished for now! %s Tugashi lozim kartalar halicha yo\'q Qurilma xotirasi o\'rnatilmagan Sinxronlash diff --git a/AnkiDroid/src/main/res/values-ve/01-core.xml b/AnkiDroid/src/main/res/values-ve/01-core.xml index 2a0dd54cb663..a7c4ad222d5c 100644 --- a/AnkiDroid/src/main/res/values-ve/01-core.xml +++ b/AnkiDroid/src/main/res/values-ve/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-vi/01-core.xml b/AnkiDroid/src/main/res/values-vi/01-core.xml index 6dc2d895eb64..413334788559 100644 --- a/AnkiDroid/src/main/res/values-vi/01-core.xml +++ b/AnkiDroid/src/main/res/values-vi/01-core.xml @@ -128,6 +128,7 @@ Tìm kiếm bộ thẻ Tên bộ thẻ không hợp lệ Chúc mừng! Bây giờ bạn đã hoàn thành. + Deck finished for now! %s Chưa có thẻ nào tới hạn Chưa gắn ổ lưu trữ thiết bị Đồng bộ diff --git a/AnkiDroid/src/main/res/values-wo/01-core.xml b/AnkiDroid/src/main/res/values-wo/01-core.xml index 0b47452e37c2..f7ae69e0b93e 100644 --- a/AnkiDroid/src/main/res/values-wo/01-core.xml +++ b/AnkiDroid/src/main/res/values-wo/01-core.xml @@ -128,6 +128,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-xh/01-core.xml b/AnkiDroid/src/main/res/values-xh/01-core.xml index 2a0dd54cb663..a7c4ad222d5c 100644 --- a/AnkiDroid/src/main/res/values-xh/01-core.xml +++ b/AnkiDroid/src/main/res/values-xh/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-yue/01-core.xml b/AnkiDroid/src/main/res/values-yue/01-core.xml index 324d945c5ebc..ab8241c241a5 100644 --- a/AnkiDroid/src/main/res/values-yue/01-core.xml +++ b/AnkiDroid/src/main/res/values-yue/01-core.xml @@ -128,6 +128,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync diff --git a/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml b/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml index 01b2626d2a66..8f3f30fd48e8 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml @@ -128,6 +128,7 @@ 牌组搜索 无效的牌组名称 恭喜!你已经完成了目前的学习任务。 + Deck finished for now! %s 没有卡片待复习。 未挂载储存设备 同步 diff --git a/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml b/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml index 8e816bfaaafc..cf6d1ad82670 100644 --- a/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml +++ b/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml @@ -129,6 +129,7 @@ 牌組搜尋 無效牌組名稱 Congratulations! You have finished for now. + Deck finished for now! %s 尚無到期的卡片。 儲存裝置未掛載 同步 diff --git a/AnkiDroid/src/main/res/values-zu/01-core.xml b/AnkiDroid/src/main/res/values-zu/01-core.xml index 2a0dd54cb663..a7c4ad222d5c 100644 --- a/AnkiDroid/src/main/res/values-zu/01-core.xml +++ b/AnkiDroid/src/main/res/values-zu/01-core.xml @@ -131,6 +131,7 @@ Deck Search Invalid deck name Congratulations! You have finished for now. + Deck finished for now! %s No cards are due yet Device storage not mounted Sync From 94de856406ea3627302c82c28a7c261a824fcae4 Mon Sep 17 00:00:00 2001 From: Sumit Singh Date: Tue, 4 Jun 2024 17:42:19 +0530 Subject: [PATCH 070/138] Implement hold to record functionality --- .../java/com/ichi2/anki/ui/OnHoldListener.kt | 61 +++++++++++++++++++ .../ichi2/audio/AudioRecordingController.kt | 28 +++++++-- 2 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/ui/OnHoldListener.kt diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/OnHoldListener.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/OnHoldListener.kt new file mode 100644 index 000000000000..ed26f934d7bb --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/OnHoldListener.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2024 Sumit Singh + * Copyright (c) 2024 David Allison + * + * 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 . + */ + +package com.ichi2.anki.ui + +import android.view.MotionEvent +import android.view.View +import timber.log.Timber + +interface OnHoldListener { + fun onTouchStart() + fun onHoldEnd() +} + +fun View.setOnHoldListener(listener: OnHoldListener) { + val listenerWrapper = object : View.OnTouchListener, View.OnLongClickListener { + var isHolding = false + + override fun onTouch(v: View?, event: MotionEvent?): Boolean { + when (event?.action) { + MotionEvent.ACTION_DOWN -> { + Timber.v("ACTION_DOWN: onTouchStart()") + listener.onTouchStart() + } + MotionEvent.ACTION_UP -> { + Timber.v("ACTION_UP") + if (isHolding) { + Timber.v("onHoldEnd()") + listener.onHoldEnd() + } + isHolding = false + } + } + return false + } + + override fun onLongClick(v: View?): Boolean { + Timber.v("onLongClick") + // this method is called once the threshold for a long press is reached + // not when the long press is released + isHolding = true + return true + } + } + this.setOnLongClickListener(listenerWrapper) + this.setOnTouchListener(listenerWrapper) +} diff --git a/AnkiDroid/src/main/java/com/ichi2/audio/AudioRecordingController.kt b/AnkiDroid/src/main/java/com/ichi2/audio/AudioRecordingController.kt index f9243883f478..78b0358a9df9 100644 --- a/AnkiDroid/src/main/java/com/ichi2/audio/AudioRecordingController.kt +++ b/AnkiDroid/src/main/java/com/ichi2/audio/AudioRecordingController.kt @@ -41,6 +41,8 @@ import com.ichi2.anki.multimediacard.fields.FieldControllerBase import com.ichi2.anki.multimediacard.fields.IFieldController import com.ichi2.anki.showThemedToast import com.ichi2.anki.snackbar.showSnackbar +import com.ichi2.anki.ui.OnHoldListener +import com.ichi2.anki.ui.setOnHoldListener import com.ichi2.anki.utils.elapsed import com.ichi2.anki.utils.formatAsString import com.ichi2.annotations.NeedsTest @@ -186,10 +188,28 @@ class AudioRecordingController : setUpMediaPlayer() audioTimer = AudioTimer(this, this) - recordButton.setOnClickListener { - Timber.i("primary 'record' button clicked") - controlAudioRecorder() - } + + // if the recorder is in the 'cleared' state + // holding the 'record' button should start a recording + // releasing the 'record' button should complete the recording + // TODO: remove haptics from the long press - the 'buzz' can be heard on the recording + recordButton.setOnHoldListener(object : OnHoldListener { + override fun onTouchStart() { + Timber.d("pressed 'record' button'") + controlAudioRecorder() + } + + override fun onHoldEnd() { + Timber.d("finished holding 'record' button'") + if (state is ImmediatePlayback) { + controlAudioRecorder() + } else { + // if we're recording audio to add permanently, + // releasing the button after a long press should be 'save', not 'pause' + saveButton?.performClick() + } + } + }) playAudioButton.setOnClickListener { Timber.i("play/pause clicked") From 7a48b84ffb93d69fe4d64307cd84d57ac0be624b Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Sat, 8 Jun 2024 21:52:19 +0100 Subject: [PATCH 071/138] refactor(card-browser): remove rowId references CardBrowser will move to render using either the card id or the note id Our data is currently ALWAYS CardIds, which may be transformed into NoteIds We had code assuming that the CardId was always used which needed to be modified to handle the case that a DB call is needed to map NoteId <-> CardId * selectedRowIds * allCardIds * Now needs to be `suspend` * get[Selected]CardIdAtPosition * Now needs to be `suspend` Issue 11889 --- .../main/java/com/ichi2/anki/CardBrowser.kt | 115 ++++++++++-------- .../anki/browser/CardBrowserViewModel.kt | 103 ++++++++-------- .../java/com/ichi2/anki/CardBrowserTest.kt | 19 +-- .../anki/browser/CardBrowserViewModelTest.kt | 8 +- 4 files changed, 131 insertions(+), 114 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt index b424e4b32288..e8db2b486827 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt @@ -295,9 +295,6 @@ open class CardBrowser : } } - private val selectedRowIds: List - get() = viewModel.selectedRowIds - @MainThread @NeedsTest("search bar is set after selecting a saved search as first action") private fun searchForQuery(query: String) { @@ -528,10 +525,12 @@ open class CardBrowser : cb.toggle() viewModel.toggleRowSelectionAtPosition(position) } else { - // load up the card selected on the list - val clickedCardId = viewModel.getCardIdAtPosition(position) - saveScrollingState(position) - openNoteEditorForCard(clickedCardId) + launchCatchingTask { + // load up the card selected on the list + val clickedCardId = viewModel.queryCardIdAtPosition(position) + saveScrollingState(position) + openNoteEditorForCard(clickedCardId) + } } } @KotlinCleanup("helper function for min/max range") @@ -539,15 +538,17 @@ open class CardBrowser : if (viewModel.isInMultiSelectMode) { viewModel.selectRowsBetweenPositions(lastSelectedPosition, position) } else { - lastSelectedPosition = position - saveScrollingState(position) - - // click on whole cell triggers select - val cb = view!!.findViewById(R.id.card_checkbox) - cb.toggle() - viewModel.toggleRowSelectionAtPosition(position) - recenterListView(view) - cardsAdapter.notifyDataSetChanged() + launchCatchingTask { + lastSelectedPosition = position + saveScrollingState(position) + + // click on whole cell triggers select + val cb = view!!.findViewById(R.id.card_checkbox) + cb.toggle() + viewModel.toggleRowSelectionAtPosition(position) + recenterListView(view) + cardsAdapter.notifyDataSetChanged() + } } true } @@ -630,7 +631,7 @@ open class CardBrowser : @NeedsTest("Test that the mark get toggled as expected for a list of selected cards") @VisibleForTesting fun toggleMark() = launchCatchingTask { - withProgress { viewModel.toggleMark(selectedRowIds) } + withProgress { viewModel.toggleMark() } cardsAdapter.notifyDataSetChanged() } @@ -646,10 +647,10 @@ open class CardBrowser : viewModel.endMultiSelectMode() } - private fun openNoteEditorForCurrentlySelectedNote() { + private fun openNoteEditorForCurrentlySelectedNote() = launchCatchingTask { try { // Just select the first one. It doesn't particularly matter if there's a multiselect occurring. - openNoteEditorForCard(selectedRowIds[0]) + openNoteEditorForCard(viewModel.querySelectedCardIdAtPosition(0)) } catch (e: Exception) { Timber.w(e, "Error Opening Note Editor") showSnackbar( @@ -1055,28 +1056,29 @@ open class CardBrowser : R.id.action_reposition_cards -> { Timber.i("CardBrowser:: Reposition button pressed") if (warnUserIfInNotesOnlyMode()) return true - // `selectedRowIds` getter does a lot of work so save it in a val beforehand - val selectedCardIds = selectedRowIds - // Only new cards may be repositioned (If any non-new found show error dialog and return false) - if (selectedCardIds.any { getColUnsafe.getCard(it).queue != Consts.QUEUE_TYPE_NEW }) { - showDialogFragment( - SimpleMessageDialog.newInstance( - title = getString(R.string.vague_error), - message = getString(R.string.reposition_card_not_new_error), - reload = false + launchCatchingTask { + val selectedCardIds = viewModel.queryAllSelectedCardIds() + // Only new cards may be repositioned (If any non-new found show error dialog and return false) + if (selectedCardIds.any { getColUnsafe.getCard(it).queue != Consts.QUEUE_TYPE_NEW }) { + showDialogFragment( + SimpleMessageDialog.newInstance( + title = getString(R.string.vague_error), + message = getString(R.string.reposition_card_not_new_error), + reload = false + ) ) - ) - return false - } - val repositionDialog = IntegerDialog().apply { - setArgs( - title = this@CardBrowser.getString(R.string.reposition_card_dialog_title), - prompt = this@CardBrowser.getString(R.string.reposition_card_dialog_message), - digits = 5 - ) - setCallbackRunnable(::repositionCardsNoValidation) + return@launchCatchingTask + } + val repositionDialog = IntegerDialog().apply { + setArgs( + title = this@CardBrowser.getString(R.string.reposition_card_dialog_title), + prompt = this@CardBrowser.getString(R.string.reposition_card_dialog_message), + digits = 5 + ) + setCallbackRunnable(::repositionCardsNoValidation) + } + showDialogFragment(repositionDialog) } - showDialogFragment(repositionDialog) return true } R.id.action_edit_note -> { @@ -1084,9 +1086,11 @@ open class CardBrowser : return super.onOptionsItemSelected(item) } R.id.action_view_card_info -> { - viewModel.cardInfoDestination?.let { destination -> - val intent: Intent = destination.toIntent(this) - startActivity(intent) + launchCatchingTask { + viewModel.queryCardInfoDestination()?.let { destination -> + val intent: Intent = destination.toIntent(this@CardBrowser) + startActivity(intent) + } } return true } @@ -1106,7 +1110,7 @@ open class CardBrowser : override fun exportDialogsFactory(): ExportDialogsFactory = exportingDelegate.dialogsFactory private fun exportSelected() = launchCatchingTask { - val (type, selectedIds) = viewModel.getSelectionExportData() ?: return@launchCatchingTask + val (type, selectedIds) = viewModel.querySelectionExportData() ?: return@launchCatchingTask ExportDialogFragment.newInstance(type, selectedIds).show(supportFragmentManager, "exportDialog") } @@ -1128,8 +1132,11 @@ open class CardBrowser : private fun onResetProgress() { if (warnUserIfInNotesOnlyMode()) return - val dialog = ForgetCardsDialog.newInstance(viewModel.selectedRowIds) - showDialogFragment(dialog) + launchCatchingTask { + val cardIds = viewModel.queryAllSelectedCardIds() + val dialog = ForgetCardsDialog.newInstance(cardIds = cardIds) + showDialogFragment(dialog) + } } @VisibleForTesting @@ -1146,8 +1153,10 @@ open class CardBrowser : } private fun onPreview() { - val intentData = viewModel.previewIntentData - onPreviewCardsActivityResult.launch(getPreviewIntent(intentData.currentIndex, intentData.previewerIdsFile)) + launchCatchingTask { + val intentData = viewModel.queryPreviewIntentData() + onPreviewCardsActivityResult.launch(getPreviewIntent(intentData.currentIndex, intentData.previewerIdsFile)) + } } private fun getPreviewIntent(index: Int, previewerIdsFile: PreviewerIdsFile): Intent { @@ -1205,7 +1214,7 @@ open class CardBrowser : get() = intent.getLongExtra("currentCard", -1) private fun showEditTagsDialog() { - if (selectedRowIds.isEmpty()) { + if (!viewModel.hasSelectedAnyRows()) { Timber.d("showEditTagsDialog: called with empty selection") } @@ -1441,10 +1450,10 @@ open class CardBrowser : * For more info on [selectedTags] and [indeterminateTags] see [com.ichi2.anki.dialogs.tags.TagsDialogListener.onSelectedTags] */ private suspend fun editSelectedCardsTags(selectedTags: List, indeterminateTags: List) = withProgress { + val selectedNoteIds = viewModel.queryAllSelectedNoteIds().distinct() undoableOp { - val selectedNotes = selectedRowIds - .map { cardId -> getCard(cardId).note() } - .distinct() + val selectedNotes = selectedNoteIds + .map { noteId -> getNote(noteId) } .onEach { note -> val previousTags: List = note.tags val updatedTags = getUpdatedTags(previousTags, selectedTags, indeterminateTags) @@ -1535,8 +1544,8 @@ open class CardBrowser : updatePreviewMenuItem() invalidateOptionsMenu() // maybe the availability of undo changed } - private fun saveScrollingState(position: Int) { - oldCardId = viewModel.getCardIdAtPosition(position) + private suspend fun saveScrollingState(position: Int) { + oldCardId = viewModel.queryCardIdAtPosition(position) oldCardTopOffset = calculateTopOffset(position) } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index 863e0d652e3d..1e574adc0836 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -31,7 +31,7 @@ import com.ichi2.anki.CollectionManager.withCol import com.ichi2.anki.DeckSpinnerSelection.Companion.ALL_DECKS_ID import com.ichi2.anki.Flag import com.ichi2.anki.PreviewerDestination -import com.ichi2.anki.export.ExportDialogFragment +import com.ichi2.anki.export.ExportDialogFragment.* import com.ichi2.anki.launchCatchingIO import com.ichi2.anki.model.CardStateFilter import com.ichi2.anki.model.CardsOrNotes @@ -39,7 +39,6 @@ import com.ichi2.anki.model.CardsOrNotes.* import com.ichi2.anki.model.SortType import com.ichi2.anki.pages.CardInfoDestination import com.ichi2.anki.preferences.SharedPreferencesProvider -import com.ichi2.anki.servicelayer.CardService import com.ichi2.anki.setUserFlag import com.ichi2.annotations.NeedsTest import com.ichi2.libanki.Card @@ -110,9 +109,6 @@ class CardBrowserViewModel( val flowOfSearchState = MutableSharedFlow() - /** The CardIds of all the cards in the results */ - val allCardIds get() = cards.map { c -> c.id } - var searchTerms = "" private set private var restrictOnDeck: String = "" @@ -167,23 +163,24 @@ class CardBrowserViewModel( val flowOfSelectedRows: Flow> = flowOf(selectedRows).combine(refreshSelectedRowsFlow) { row, _ -> row } - /** A list of either: - * * [CardsOrNotes.CARDS] all selected card Ids - * * [CardsOrNotes.NOTES] one selected Id for every note - */ - val selectedRowIds: List - get() = selectedRows.map { c -> c.id } - suspend fun queryAllSelectedCardIds(): List = when (cardsOrNotes) { - CARDS -> selectedRowIds + CARDS -> selectedRows.map { c -> c.id } NOTES -> selectedRows .flatMap { row -> withCol { cardIdsOfNote(nid = row.card.nid) } } } // TODO: move the tag computation to ViewModel - suspend fun queryAllSelectedNoteIds(): List = - withCol { notesOfCards(selectedRowIds) } + suspend fun queryAllSelectedNoteIds(): List { + val cardIds = selectedRows.map { c -> c.id } + return withCol { notesOfCards(cids = cardIds) } + } + + @Suppress("RedundantSuspendModifier") // will be necessary + @VisibleForTesting + internal suspend fun queryAllCardIds(): List { + return cards.map { it.id } + } var lastSelectedPosition = 0 @@ -212,11 +209,11 @@ class CardBrowserViewModel( val flowOfDeckId = MutableStateFlow(lastDeckId) val deckId get() = flowOfDeckId.value - val cardInfoDestination: CardInfoDestination? - get() { - val firstSelectedCard = selectedRowIds.firstOrNull() ?: return null - return CardInfoDestination(firstSelectedCard) - } + suspend fun queryCardInfoDestination(): CardInfoDestination? { + // TODO: Inefficient + val firstSelectedCard = queryAllSelectedCardIds().firstOrNull() ?: return null + return CardInfoDestination(firstSelectedCard) + } private suspend fun getInitialDeck(): DeckId { // TODO: Handle the launch intent @@ -339,8 +336,9 @@ class CardBrowserViewModel( * If one or more card is unmarked, all will be marked, * otherwise, they will be unmarked */ - suspend fun toggleMark(cardIds: List) { - if (!hasSelectedAnyRows()) { + suspend fun toggleMark() { + val cardIds = queryAllSelectedCardIds() + if (cardIds.isEmpty()) { Timber.i("Not marking cards - nothing selected") return } @@ -357,15 +355,18 @@ class CardBrowserViewModel( tags.bulkRemove(noteIds, "marked") } } - selectedRows.forEach { it.reload() } + val modifiedIds = cardIds.toSet() + cards.filter { modifiedIds.contains(it.id) }.forEach { it.reload() } } /** * Deletes the selected notes, * @return the number of deleted notes */ - suspend fun deleteSelectedNotes(): Int = - undoableOp { removeNotes(cids = selectedRowIds) }.count + suspend fun deleteSelectedNotes(): Int { + val cardIds = queryAllSelectedCardIds() + return undoableOp { removeNotes(cids = cardIds) }.count + } fun setCardsOrNotes(newValue: CardsOrNotes) = viewModelScope.launch { Timber.i("setting mode to %s", newValue) @@ -530,14 +531,11 @@ class CardBrowserViewModel( return BuryResult(wasBuried = wasBuried!!, count = cardIds.size) } - suspend fun getSelectionExportData(): Pair>? { + suspend fun querySelectionExportData(): Pair>? { if (!hasSelectedAnyRows()) return null return when (cardsOrNotes) { - CARDS -> Pair(ExportDialogFragment.ExportType.Cards, selectedRowIds) - NOTES -> Pair( - ExportDialogFragment.ExportType.Notes, - withCol { CardService.selectedNoteIds(selectedRowIds) } - ) + CARDS -> Pair(ExportType.Cards, queryAllSelectedCardIds()) + NOTES -> Pair(ExportType.Notes, queryAllSelectedNoteIds()) } } @@ -545,16 +543,17 @@ class CardBrowserViewModel( * @see [com.ichi2.libanki.sched.Scheduler.sortCards] * @return the number of cards which were repositioned */ - suspend fun repositionSelectedRows(position: Int) = undoableOp { - sched.sortCards(selectedRowIds, position, 1, shuffle = false, shift = true) - }.count + suspend fun repositionSelectedRows(position: Int): Int { + val ids = queryAllSelectedCardIds() + return undoableOp { + sched.sortCards(cids = ids, position, 1, shuffle = false, shift = true) + }.count + } /** Returns the number of rows of the current result set */ val rowCount: Int get() = cards.size() - fun getCardIdAtPosition(position: Int): CardId = cards[position].id - fun getRowAtPosition(position: Int) = cards[position] /** Given a card ID, returns a position-aware card */ @@ -640,23 +639,21 @@ class CardBrowserViewModel( } /** Previewing */ - - val previewIntentData: PreviewerDestination - get() { - // If in NOTES mode, we show one Card per Note, as this matches Anki Desktop - return if (selectedRowCount() > 1) { - PreviewerDestination(currentIndex = 0, PreviewerIdsFile(cacheDir, selectedRowIds)) - } else { - // Preview all cards, starting from the one that is currently selected - val startIndex = indexOfFirstCheckedCard() ?: 0 - PreviewerDestination(startIndex, PreviewerIdsFile(cacheDir, allCardIds)) - } + suspend fun queryPreviewIntentData(): PreviewerDestination { + // If in NOTES mode, we show one Card per Note, as this matches Anki Desktop + return if (selectedRowCount() > 1) { + PreviewerDestination(currentIndex = 0, PreviewerIdsFile(cacheDir, queryAllSelectedCardIds())) + } else { + // Preview all cards, starting from the one that is currently selected + val startIndex = indexOfFirstCheckedCard() ?: 0 + PreviewerDestination(startIndex, PreviewerIdsFile(cacheDir, queryAllCardIds())) } + } /** @return the index of the first checked card in [cards], or `null` if no cards are checked */ private fun indexOfFirstCheckedCard(): Int? { val idToFind = selectedRows.firstOrNull()?.id ?: return null - return allCardIds.indexOf(idToFind) + return cards.map { it.id }.indexOf(idToFind) } fun setSearchQueryExpanded(expand: Boolean) { @@ -749,6 +746,16 @@ class CardBrowserViewModel( flowOfCardsUpdated.emit(Unit) } + suspend fun queryCardIdAtPosition(index: Int): CardId { + // TODO: Slow - this will be refactored + return queryAllCardIds()[index] + } + + suspend fun querySelectedCardIdAtPosition(index: Int): CardId { + // TODO: Slow - this will be refactored + return queryAllSelectedCardIds()[index] + } + companion object { const val DISPLAY_COLUMN_1_KEY = "cardBrowserColumn1" const val DISPLAY_COLUMN_2_KEY = "cardBrowserColumn2" diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt index 740a186f530c..f91fabd4040f 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt @@ -372,7 +372,7 @@ class CardBrowserTest : RobolectricTest() { // check if all card flags turned green assertThat( "All cards should be flagged", - cardBrowser.viewModel.allCardIds + cardBrowser.viewModel.queryAllCardIds() .map { cardId -> getCardFlagAfterFlagChangeDone(cardBrowser, cardId) } .all { flag1 -> flag1 == Flag.GREEN.code } ) @@ -430,7 +430,7 @@ class CardBrowserTest : RobolectricTest() { @Test @Flaky(os = OS.WINDOWS, "IllegalStateException: Card '1596783600440' not found") - fun previewWorksAfterSort() { + fun previewWorksAfterSort() = runTest { // #7286 val cid1 = addNoteUsingBasicModel("Hello", "World").cards()[0].id val cid2 = addNoteUsingBasicModel("Hello2", "World2").cards()[0].id @@ -441,7 +441,7 @@ class CardBrowserTest : RobolectricTest() { assertThat(b.getPropertiesForCardId(cid2).position, equalTo(1)) b.selectRowsWithPositions(0) - val previewIntent = b.viewModel.previewIntentData + val previewIntent = b.viewModel.queryPreviewIntentData() assertThat("before: index", previewIntent.currentIndex, equalTo(0)) assertThat( "before: cards", @@ -456,7 +456,7 @@ class CardBrowserTest : RobolectricTest() { assertThat(b.getPropertiesForCardId(cid2).position, equalTo(0)) b.replaceSelectionWith(intArrayOf(0)) - val intentAfterReverse = b.viewModel.previewIntentData + val intentAfterReverse = b.viewModel.queryPreviewIntentData() assertThat("after: index", intentAfterReverse.currentIndex, equalTo(0)) assertThat( "after: cards", @@ -567,7 +567,7 @@ class CardBrowserTest : RobolectricTest() { @Test @Ignore("Doesn't work - but should") - fun dataUpdatesAfterUndoReposition() { + fun dataUpdatesAfterUndoReposition() = runTest { val b = getBrowserWithNotes(1) b.selectRowsWithPositions(0) @@ -747,14 +747,15 @@ class CardBrowserTest : RobolectricTest() { } } - private fun getCheckedCard(b: CardBrowser): CardCache { - val ids = b.viewModel.selectedRowIds + private suspend fun getCheckedCard(b: CardBrowser): CardCache { + val ids = b.viewModel.queryAllSelectedCardIds() assertThat("only one card expected to be checked", ids, hasSize(1)) return b.getPropertiesForCardId(ids[0]) } - private fun deleteCardAtPosition(browser: CardBrowser, positionToCorrupt: Int) { - removeCardFromCollection(browser.viewModel.allCardIds[positionToCorrupt]) + private suspend fun deleteCardAtPosition(browser: CardBrowser, positionToCorrupt: Int) { + val id = browser.viewModel.queryCardIdAtPosition(positionToCorrupt) + removeCardFromCollection(id) browser.clearCardData(positionToCorrupt) } diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index 2a21f91bc23a..099c370f0a42 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -189,7 +189,7 @@ class CardBrowserViewModelTest : JvmTest() { @Test fun `toggle bury - queue changes`() = runViewModelTest(notes = 1) { selectRowAtPosition(0) - fun getQueue() = col.getCard(selectedRowIds.single()).queue + suspend fun getQueue() = col.getCard(queryAllSelectedCardIds().single()).queue assertThat("initial queue = NEW", getQueue(), equalTo(QUEUE_TYPE_NEW)) @@ -470,14 +470,14 @@ class CardBrowserViewModelTest : JvmTest() { @Test fun `export - no selection`() = runViewModelTest(notes = 2) { - assertNull(getSelectionExportData(), "no export data if no selection") + assertNull(querySelectionExportData(), "no export data if no selection") } @Test fun `export - one card`() = runViewModelTest(notes = 2) { selectRowsWithPositions(0) - val (exportType, ids) = assertNotNull(getSelectionExportData()) + val (exportType, ids) = assertNotNull(querySelectionExportData()) assertThat(exportType, equalTo(ExportDialogFragment.ExportType.Cards)) assertThat(ids, hasSize(1)) @@ -489,7 +489,7 @@ class CardBrowserViewModelTest : JvmTest() { fun `export - one note`() = runViewModelNotesTest(notes = 2) { selectRowsWithPositions(0) - val (exportType, ids) = assertNotNull(getSelectionExportData()) + val (exportType, ids) = assertNotNull(querySelectionExportData()) assertThat(exportType, equalTo(ExportDialogFragment.ExportType.Notes)) assertThat(ids, hasSize(1)) From 3921309d9e752a6f76cb9606137c51a3c0659a68 Mon Sep 17 00:00:00 2001 From: AnkiDroid Translations Date: Wed, 12 Jun 2024 17:05:11 +0000 Subject: [PATCH 072/138] Updated strings from Crowdin --- AnkiDroid/src/main/res/values-eo/02-strings.xml | 8 ++++---- AnkiDroid/src/main/res/values-eo/03-dialogs.xml | 2 +- AnkiDroid/src/main/res/values-eo/04-network.xml | 2 +- AnkiDroid/src/main/res/values-ja/01-core.xml | 2 +- AnkiDroid/src/main/res/values-ja/04-network.xml | 2 +- AnkiDroid/src/main/res/values-tr/01-core.xml | 12 ++++++------ AnkiDroid/src/main/res/values-tr/02-strings.xml | 4 ++-- AnkiDroid/src/main/res/values-tr/03-dialogs.xml | 10 +++++----- AnkiDroid/src/main/res/values-tr/04-network.xml | 2 +- AnkiDroid/src/main/res/values-zh-rCN/01-core.xml | 2 +- 10 files changed, 23 insertions(+), 23 deletions(-) diff --git a/AnkiDroid/src/main/res/values-eo/02-strings.xml b/AnkiDroid/src/main/res/values-eo/02-strings.xml index adb6f825c60f..2a73204c4880 100644 --- a/AnkiDroid/src/main/res/values-eo/02-strings.xml +++ b/AnkiDroid/src/main/res/values-eo/02-strings.xml @@ -361,8 +361,8 @@ %d cards unburied Reposition - Record - Stop - Play - Next + Registri + Haltigi + Ludi + Antaŭen diff --git a/AnkiDroid/src/main/res/values-eo/03-dialogs.xml b/AnkiDroid/src/main/res/values-eo/03-dialogs.xml index e51af167b9ba..7f7693084fa8 100644 --- a/AnkiDroid/src/main/res/values-eo/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-eo/03-dialogs.xml @@ -255,7 +255,7 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. - Open + Malfermi Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-eo/04-network.xml b/AnkiDroid/src/main/res/values-eo/04-network.xml index eadddf563898..006ee7857a1e 100644 --- a/AnkiDroid/src/main/res/values-eo/04-network.xml +++ b/AnkiDroid/src/main/res/values-eo/04-network.xml @@ -64,7 +64,7 @@ Elsaluti Restarigi pasvorton Ĉu vi forgesis la retpoŝtadreson? - Signing in + Aliĝado Agordoj por XXX Samtempigo diff --git a/AnkiDroid/src/main/res/values-ja/01-core.xml b/AnkiDroid/src/main/res/values-ja/01-core.xml index 3a3f5a904a1a..ff326af1ec29 100644 --- a/AnkiDroid/src/main/res/values-ja/01-core.xml +++ b/AnkiDroid/src/main/res/values-ja/01-core.xml @@ -128,7 +128,7 @@ デッキを検索 無効なデッキ名です おめでとうございます! このデッキの現在の課題をすべて達成しました! - Deck finished for now! %s + このデッキの現在の課題をすべて達成しました。\nなお、%s このデッキの今日の課題はまだ残っていますが、どれもまだ学習予定時刻に達していません デバイスのストレージがマウントされていません 同期 diff --git a/AnkiDroid/src/main/res/values-ja/04-network.xml b/AnkiDroid/src/main/res/values-ja/04-network.xml index 7d119f9063a6..9e941e7424c5 100644 --- a/AnkiDroid/src/main/res/values-ja/04-network.xml +++ b/AnkiDroid/src/main/res/values-ja/04-network.xml @@ -70,7 +70,7 @@ 同期 この端末側のコレクションによる完全同期が完了しました コレクションの同期が完了しました - Collection synced. Media is being synced in the background. + コレクションの同期が完了しました。メディアの同期はバックグラウンドで進行します。 データベースが破損しています。同期を再試行する前にデータベースを修復してください。修復に関する情報は %s を参照してください。 ローカル diff --git a/AnkiDroid/src/main/res/values-tr/01-core.xml b/AnkiDroid/src/main/res/values-tr/01-core.xml index a464713a7063..4e0ce1b27222 100644 --- a/AnkiDroid/src/main/res/values-tr/01-core.xml +++ b/AnkiDroid/src/main/res/values-tr/01-core.xml @@ -87,7 +87,7 @@ Tekrarla Konturu geri al Hepsini desteye taşı - Gizlemeyi geri al + Gömülenleri çıkar Desteyi yeniden adlandır Kısayol oluştur Kartları göz at @@ -96,11 +96,11 @@ Not ekle Hesabı senkronize et Gizle / Sil - Kartı gizle - Notu gizle + Kartı göm + Notu göm Kartı askıya al Notu Askıya Al - Gizle + Göm Askıya Al Notu sil Bayrak @@ -131,7 +131,7 @@ Deste Ara Geçersiz deste adı Tebrikler! Şimdilik bitirdiniz. - Deck finished for now! %s + Deste şimdilik bitti! %s Henüz sırası gelmiş kart yok Cihaz hafızası takılı değil Senkronize et @@ -248,5 +248,5 @@ Resim Örtüsü Hesabı sil - Instant card + Anında kart diff --git a/AnkiDroid/src/main/res/values-tr/02-strings.xml b/AnkiDroid/src/main/res/values-tr/02-strings.xml index f065697f072d..2a460d6fdded 100644 --- a/AnkiDroid/src/main/res/values-tr/02-strings.xml +++ b/AnkiDroid/src/main/res/values-tr/02-strings.xml @@ -359,8 +359,8 @@ Kopyalanamadı \"Notlar\" modunda kullanılamıyor - %d card unburied - %d cards unburied + %d kart çıkarıldı + %d kart çıkarıldı Yerini değiştir Kayda başla diff --git a/AnkiDroid/src/main/res/values-tr/03-dialogs.xml b/AnkiDroid/src/main/res/values-tr/03-dialogs.xml index 955b433252ea..613e07fced42 100644 --- a/AnkiDroid/src/main/res/values-tr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tr/03-dialogs.xml @@ -253,10 +253,10 @@ En erken En geç - Cloze Type Note Required - No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. - Open - Single tap text to cloze + Boşluklu Türden Not Gerekiyor + Boşluklu türden not bulunmuyor, Not Düzenleyiciyi açın ya da Boşluklu türden bir not ekledikten sonra yeniden deneyin. + + Boşluk bırakmak için metne bir kez dokunun - The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + Sistem WebView\'su güncel değil. Bazı özellikler doğru çalışmayacak. Lütfen güncelleyin.\n\nYüklü sürüm: %1$d\nGereken en düşük sürüm: %2$d diff --git a/AnkiDroid/src/main/res/values-tr/04-network.xml b/AnkiDroid/src/main/res/values-tr/04-network.xml index 1d9e27ed66dd..ec2a56dbf171 100644 --- a/AnkiDroid/src/main/res/values-tr/04-network.xml +++ b/AnkiDroid/src/main/res/values-tr/04-network.xml @@ -70,7 +70,7 @@ Senkronizasyon Yerelden tam senkronizasyon Koleksiyon senkronize edildi - Collection synced. Media is being synced in the background. + Koleksiyon senkronize edildi. Medya arkaplanda senkronize ediliyor. Veritabanınız bozuk. Lütfen eşitlemeyi yeniden denemeden önce onu düzeltin.\n\nVeritabanınızı onarmak hakkında bilgi için %s bakın. Yerel diff --git a/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml b/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml index 8f3f30fd48e8..fff36ec9e262 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml @@ -128,7 +128,7 @@ 牌组搜索 无效的牌组名称 恭喜!你已经完成了目前的学习任务。 - Deck finished for now! %s + 牌组目前已完成! %s 没有卡片待复习。 未挂载储存设备 同步 From 43d1e67f3e802563e7b9041200d44a7a4ae35a94 Mon Sep 17 00:00:00 2001 From: Ashish Yadav <48384865+criticalAY@users.noreply.github.com> Date: Tue, 11 Jun 2024 03:34:02 +0530 Subject: [PATCH 073/138] refactor: init deckspinner accept optional layout --- .../src/main/java/com/ichi2/anki/DeckSpinnerSelection.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/DeckSpinnerSelection.kt b/AnkiDroid/src/main/java/com/ichi2/anki/DeckSpinnerSelection.kt index f2e980f90c26..5c9875af3eed 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/DeckSpinnerSelection.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/DeckSpinnerSelection.kt @@ -21,6 +21,7 @@ import android.view.ViewGroup import android.widget.ArrayAdapter import android.widget.Spinner import android.widget.TextView +import androidx.annotation.LayoutRes import androidx.annotation.MainThread import androidx.appcompat.app.ActionBar import androidx.appcompat.app.AppCompatActivity @@ -84,10 +85,10 @@ class DeckSpinnerSelection( } @MainThread // spinner.adapter - fun initializeNoteEditorDeckSpinner(col: Collection) { + fun initializeNoteEditorDeckSpinner(col: Collection, @LayoutRes layoutResource: Int = R.layout.multiline_spinner_item) { dropDownDecks = computeDropDownDecks(col, includeFiltered = false).toMutableList() val deckNames = dropDownDecks.map { it.name } - val noteDeckAdapter: ArrayAdapter = object : ArrayAdapter(context, R.layout.multiline_spinner_item, deckNames as List) { + val noteDeckAdapter: ArrayAdapter = object : ArrayAdapter(context, layoutResource, deckNames as List) { override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View { // Cast the drop down items (popup items) as text view val tv = super.getDropDownView(position, convertView, parent) as TextView From 32bf2c33b7e0b68a434378b318eb82593930628e Mon Sep 17 00:00:00 2001 From: Ashish Yadav <48384865+criticalAY@users.noreply.github.com> Date: Tue, 11 Jun 2024 03:35:02 +0530 Subject: [PATCH 074/138] feature: use chipGroup instead of EditText * enhancement: switch between modes using button * unitTest: added unit tests for the viewmodel * docs: viewmodel new methods documentation --- .../anki/instantnoteeditor/EditorChips.kt | 143 +++++++++++++ .../InstantEditorViewModel.kt | 201 ++++++++++++++++++ .../InstantNoteEditorActivity.kt | 132 ++++++++---- .../instantnoteeditor/TextSurroundHelper.kt | 149 ------------- .../anki/preferences/DevOptionsFragment.kt | 2 +- .../main/res/layout/instant_editor_dialog.xml | 52 ++++- .../layout/instant_editor_field_layout.xml | 1 + AnkiDroid/src/main/res/values/03-dialogs.xml | 1 - .../InstantEditorViewModelTest.kt | 80 ++++++- 9 files changed, 556 insertions(+), 205 deletions(-) create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/EditorChips.kt delete mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/TextSurroundHelper.kt diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/EditorChips.kt b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/EditorChips.kt new file mode 100644 index 000000000000..b94c3c85adbf --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/EditorChips.kt @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2024 Ashish Yadav + * + * 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 . + */ + +package com.ichi2.anki.instantnoteeditor + +import android.content.Context +import android.view.View +import androidx.annotation.OptIn +import com.google.android.material.badge.BadgeDrawable +import com.google.android.material.badge.BadgeUtils +import com.google.android.material.badge.ExperimentalBadgeUtils +import com.google.android.material.chip.Chip +import com.google.android.material.chip.ChipGroup +import timber.log.Timber + +/** + * Updates the clozeChipGroup by removing all views and re-adding chips based on the current text. + * + * This method retrieves the words from the ViewModel's field text, creates ChipData objects for each word, + * and sets up the chips with appropriate badge drawables. It also sets click listeners on each chip to + * handle the creation and updating of cloze deletions. + */ +// TODO: single chars have more margin in chip +fun Context.setupChipGroup(viewModel: InstantEditorViewModel, clozeChipGroup: ChipGroup) { + Timber.d("Setting up chip group view") + clozeChipGroup.removeAllViews() + + val words = viewModel.getWordsFromFieldText() + + val chipsData = words.map { word -> + val clozeNumber = viewModel.getWordClozeNumber(word) + + ChipData( + word, + Chip(clozeChipGroup.context), + createBadgeDrawable(this), + clozeNumber + ) + } + + chipsData.forEach { data -> + val chip = data.chip + + chip.isCheckable = true + updateChipAndBadge(data) + chip.text = viewModel.getCleanClozeWords(data.word) + + chip.setOnClickListener { + val newWord = viewModel.buildClozeText(data.word) + data.word = newWord + val newClozeNumber = viewModel.getWordClozeNumber(newWord) + + updateChipAndBadge(data.copy(clozeNumber = newClozeNumber)) + + val modifiedSentence = chipsData.joinToString(separator = " ") { it.word } + viewModel.setClozeFieldText(modifiedSentence) + } + clozeChipGroup.addView(chip) + } +} + +private fun updateChipAndBadge(data: ChipData) { + val chip = data.chip + val clozeNumber = data.clozeNumber + + if (clozeNumber == null) { + chip.isChecked = false + updateBadgeVisibilityOnView(data.chip, data.badgeDrawable, false) + } else { + data.badgeDrawable.number = clozeNumber + data.clozeNumber = clozeNumber + chip.isChecked = true + updateBadgeVisibilityOnView(data.chip, data.badgeDrawable, true) + } +} + +/** + * Creates and configures a BadgeDrawable instance. + * + * This method creates a BadgeDrawable with a specified gravity and vertical offset. + * + * @param context The context used to create the BadgeDrawable. + * @return A configured BadgeDrawable instance. + */ +private fun createBadgeDrawable(context: Context): BadgeDrawable { + return BadgeDrawable.create(context).apply { + badgeGravity = BadgeDrawable.TOP_END + verticalPadding = 0 + horizontalPadding = 0 + verticalOffset = 50 + } +} + +/** + * Attaches or detaches a BadgeDrawable to/from a view based on visibility. + * + * This method posts a runnable to the view's message queue to either attach or detach + * the BadgeDrawable, ensuring the operation is performed on the UI thread. + * + * @param view The view to which the BadgeDrawable will be attached or from which it will be detached. + * @param badgeDrawable The BadgeDrawable to be shown or hidden. + * @param visible A boolean indicating whether the BadgeDrawable should be attached (true) or detached (false). + */ +@OptIn(ExperimentalBadgeUtils::class) +private fun updateBadgeVisibilityOnView(view: View, badgeDrawable: BadgeDrawable, visible: Boolean) { + view.post { + if (visible) { + BadgeUtils.attachBadgeDrawable(badgeDrawable, view, null) + } else { + BadgeUtils.detachBadgeDrawable(badgeDrawable, view) + } + } +} + +/** + * Data class representing a chip with associated data for a cloze-deleted text. + * + * @param word The original word that was deleted from the cloze-deleted text passage. + * @param chip The chip UI element associated with this data. + * @param badgeDrawable A drawable to be displayed as a badge on the chip. + * @param clozeNumber (Optional) The number associated with the cloze deletion where this chip is used. + * If null then it means that the word is not cloze i.e. no cloze deletion + */ +private data class ChipData( + var word: String, + val chip: Chip, + val badgeDrawable: BadgeDrawable, + var clozeNumber: Int? +) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantEditorViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantEditorViewModel.kt index 3980c999ef2f..43058f9bbb6d 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantEditorViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantEditorViewModel.kt @@ -38,8 +38,10 @@ import com.ichi2.libanki.undoableOp import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch import timber.log.Timber +import kotlin.math.max /** * ViewModel for managing instant note editing functionality. @@ -52,6 +54,23 @@ class InstantEditorViewModel : ViewModel(), OnErrorListener { /** Errors or Warnings related to the edit fields that might occur when trying to save note */ val instantEditorError = MutableSharedFlow() + private val _currentClozeNumber = MutableStateFlow(1) + + val currentClozeNumber: Int + get() = _currentClozeNumber.value + + private val _currentClozeMode = MutableStateFlow(InstantNoteEditorActivity.ClozeMode.INCREMENT) + + val currentClozeMode: StateFlow = _currentClozeMode.asStateFlow() + + private val _actualClozeFieldText = MutableStateFlow(null) + + val actualClozeFieldText: StateFlow = _actualClozeFieldText.asStateFlow() + + private val _editorMode = MutableStateFlow(InstantNoteEditorActivity.EditMode.SINGLE_TAP) + + val editorMode: StateFlow = _editorMode.asStateFlow() + /** * Gets the current editor note. */ @@ -175,6 +194,171 @@ class InstantEditorViewModel : ViewModel(), OnErrorListener { instantEditorError.emit(message) } } + + private fun incrementClozeNumber() { + Timber.d("Incrementing cloze number: $currentClozeNumber") + _currentClozeNumber.value++ + } + + fun setClozeFieldText(text: String?) { + _actualClozeFieldText.value = text + } + + /** + * Creates or removes the cloze deletion for a word around the given offset. + * + * This method first checks if the provided text already contains a cloze deletion. + * If it does, it returns the clean text. If not, it creates a new cloze + * deletion for the text, optionally including punctuation if present at the end of the text. + * + * The method also handles incrementing the cloze number based on the current cloze mode. + * + * @param text the text to be converted into a cloze deletion + * @return the cloze-deleted version of the input text or clean text if already cloze + */ + fun buildClozeText(text: String): String { + val cloze = processClozeUndo(text) + if (cloze != null) { + Timber.d("Text contains cloze, removed cloze") + return cloze + } + + Timber.d("Text doesn't have cloze, selecting and adding cloze") + + val matcher = clozeBuilderPattern.findAll(text).firstOrNull() + + val clozeText: String? + + val punctuation: String? = matcher?.groups?.get(2)?.value + if (!punctuation.isNullOrEmpty()) { + val capturedWord = matcher.groups[1]?.value + clozeText = "{{c$currentClozeNumber::$capturedWord}}$punctuation" + } else { + clozeText = "{{c$currentClozeNumber::$text}}" + } + + when (currentClozeMode.value) { + InstantNoteEditorActivity.ClozeMode.INCREMENT -> { incrementClozeNumber() } + InstantNoteEditorActivity.ClozeMode.NO_INCREMENT -> { + // Do nothing here + } + } + + return clozeText + } + + /** + * This method extracts the cloze number (if present) from a given word + * that indicates a cloze deletion (a blank replaced with a number). + * If the pattern matches, it extracts the number from the captured group + * and converts it to an integer, otherwise it returns null. + * + * Example: word is {{c`number`::`text`}} then it extracts `number` + * + * @param word The word to be analyzed for a cloze number. + * @return The extracted cloze number as an integer if found, otherwise null. + */ + fun getWordClozeNumber(word: String): Int? { + val matcher = clozePattern.find(word) + return matcher?.groups?.get(1)?.value?.toIntOrNull() + } + + fun getWordsFromFieldText(): List { + val sentence = actualClozeFieldText.value ?: "" + + val words = mutableListOf() + var lastIndex = 0 + + clozePattern.findAll(sentence).forEach { matchResult -> + val cloze = matchResult.value + // Add any words between the last match and this match + val inBetween = sentence.substring(lastIndex, matchResult.range.first) + words.addAll(inBetween.trim().split(spaceRegex).filter { it.isNotEmpty() }) + words.add(cloze) + lastIndex = matchResult.range.last + 1 + } + + // Add any remaining words after the last cloze + if (lastIndex < sentence.length) { + val remaining = sentence.substring(lastIndex).trim() + words.addAll(remaining.split(spaceRegex).filter { it.isNotEmpty() }) + } + + return combineWordsWithPunctuation(words) + } + + private fun combineWordsWithPunctuation(words: List): List { + val combinedWords = mutableListOf() + + var clozeEncountered = false + + words.forEachIndexed { _, word -> + if (punctuationPattern.matches(word) && clozeEncountered) { + // Combine punctuation with the previous cloze + combinedWords[combinedWords.size - 1] += word + } else { + clozeEncountered = clozePattern.matches(word) + combinedWords.add(word) + } + } + + return combinedWords + } + + /** + * Removes the cloze deletion marker and surrounding delimiters from a word. + * + * @param word The word having a potential cloze deletion. + * @return The cleaned word with the cloze deletion marker and delimiters removed, + * or the original word if no match is found. + */ + fun getCleanClozeWords(word: String): String { + val regex = clozePattern + return regex.replace(word) { matchResult -> + (matchResult.groups[2]?.value ?: "") + (matchResult.groups[3]?.value ?: "") + } + } + + /** + * Processes a cloze-deleted word and removes cloze if any, if a user tap the words twice then + * it will detect the cloze and remove it and revert the text to its original state. + * + * @param text The text to be analyzed for cloze deletion. + * @return The processed text with the cloze deletion marker and delimiters removed + * (if applicable), the original text if no match is found, or null + * if an undo is confirmed. + */ + private fun processClozeUndo(text: String): String? { + val matchResult = clozePattern.find(text) + val capturedClozeNumber = matchResult?.groups?.get(1)?.value + if (capturedClozeNumber != null && currentClozeNumber - capturedClozeNumber.toInt() == 1) { + decrementClozeNumber() + } + if (matchResult?.groups?.get(3)?.value != null) { + return matchResult.groups[2]?.value + matchResult.groups[3]?.value + } + return matchResult?.groups?.get(2)?.value + } + + fun setEditorMode(mode: InstantNoteEditorActivity.EditMode) { + _editorMode.value = mode + } + + private fun decrementClozeNumber() { + val newValue = _currentClozeNumber.value - 1 + _currentClozeNumber.value = max(1, newValue) + } + + fun toggleClozeMode() { + val newMode = when (_currentClozeMode.value) { + InstantNoteEditorActivity.ClozeMode.INCREMENT -> InstantNoteEditorActivity.ClozeMode.NO_INCREMENT + InstantNoteEditorActivity.ClozeMode.NO_INCREMENT -> { + incrementClozeNumber() + InstantNoteEditorActivity.ClozeMode.INCREMENT + } + } + _currentClozeMode.value = newMode + } } /** @@ -216,3 +400,20 @@ sealed class SaveNoteResult { */ data class Warning(val message: String?) : SaveNoteResult() } + +/** + * A compiled regular expression pattern used to match cloze deletions within a string. + * + * This pattern is designed to identify text formatted as cloze deletions, which are commonly + * used in educational materials. The pattern follows the format: + * {{c`number`::`content`}} (optional punctuation) + */ +val clozePattern = Regex("""\{\{c(\d+)::([^}]+?)\}\}(\p{Punct}+)?""") + +private val punctuationPattern = Regex("""\p{Punct}+$""") + +/** Used when splitting words **/ +private val spaceRegex = Regex("\\s+") + +/** Used to build cloze text here word is not null **/ +private val clozeBuilderPattern = "(\\w+)(\\p{Punct}*)".toRegex() diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt index affbcae0e864..90813fd6ed85 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/InstantNoteEditorActivity.kt @@ -36,7 +36,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import com.google.android.material.button.MaterialButton -import com.google.android.material.materialswitch.MaterialSwitch +import com.google.android.material.chip.ChipGroup import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputLayout import com.ichi2.anki.AnkiActivity @@ -59,11 +59,11 @@ import com.ichi2.utils.negativeButton import com.ichi2.utils.positiveButton import com.ichi2.utils.show import com.ichi2.utils.title +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import timber.log.Timber -import kotlin.math.max /** * Single instance Activity for instantly editing and adding cloze card/s without actually opening the app, @@ -76,13 +76,17 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect private var dialogView: View? = null - private var sharedIntentText: IntentSharedText? = null + private var editMode = EditMode.ADVANCED + + private lateinit var editModeButton: MaterialButton - private lateinit var singleTapSwitch: MaterialSwitch private var editFieldsLayout: LinearLayout? = null private lateinit var clozeEditTextField: TextInputEditText private lateinit var warningTextField: FixedTextView private lateinit var instantAlertDialog: AlertDialog + private lateinit var clozeChipGroup: ChipGroup + private lateinit var singleTapLayout: LinearLayout + private lateinit var singleTapLayoutTitle: FixedTextView override fun onCreate(savedInstanceState: Bundle?) { if (showedActivityFailedScreen(savedInstanceState)) { @@ -138,7 +142,7 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect alwaysShowDefault = true, showFilteredDecks = false ).apply { - initializeNoteEditorDeckSpinner(getColUnsafe) + initializeNoteEditorDeckSpinner(getColUnsafe, android.R.layout.simple_spinner_item) launchCatchingTask { viewModel.deckId?.let { selectDeckById(it, true) } } @@ -149,7 +153,7 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect private fun handleSharedText(receivedIntent: Intent) { val sharedText = receivedIntent.getStringExtra(Intent.EXTRA_TEXT) ?: intent.getStringExtra("extra_text_key") - sharedIntentText = IntentSharedText(sharedText!!) + viewModel.setClozeFieldText(sharedText) } private fun openNoteEditor() { @@ -168,15 +172,15 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect dialogView = dv } editFieldsLayout = dialogView.findViewById(R.id.editor_fields_layout) - singleTapSwitch = dialogView.findViewById(R.id.switch_single_tap_cloze) + editModeButton = dialogView.findViewById(R.id.switch_edit_mode_button) dialogView.findViewById(R.id.open_note_editor)?.setOnClickListener { openNoteEditor() } warningTextField = dialogView.findViewById(R.id.warning_text) - dialogView.findViewById(R.id.increment_cloze_button)?.setOnClickListener { - currentClozeNumber++ - Timber.d("Incrementing cloze number: $currentClozeNumber") - } + handleClozeMode(dialogView.findViewById(R.id.increment_cloze_button)) + clozeChipGroup = dialogView.findViewById(R.id.cloze_text_chip_group) + singleTapLayout = dialogView.findViewById(R.id.single_tap_layout) + singleTapLayoutTitle = dialogView.findViewById(R.id.chip_layout_title) val editFields = createEditFields(this, viewModel.currentlySelectedNotetype.value) @@ -227,6 +231,8 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect // Anki allows multiple cloze fields, we pick the first field if (clozeFields.contains(name) && !clozeFieldsSet) { setupClozeFields(textInputEditText) + singleTapLayoutTitle.text = name + setupChipGroup(viewModel, clozeChipGroup) clozeFieldsSet = true } @@ -238,20 +244,41 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect /** Sets the copied text to the cloze field and enable the single tap gesture for that field**/ private fun setupClozeFields(textBox: TextInputEditText) { clozeEditTextField = textBox - textBox.setText(sharedIntentText?.sharedTextString) - val gestureHelper = EditTextGestureHelper( - textBox, - EditTextGestureState(singleTapSwitch.isChecked) - ) + lifecycleScope.launch { + viewModel.actualClozeFieldText.collectLatest { text -> + textBox.setText(text) + } + } + + editFieldsLayout?.visibility = View.GONE enableErrorMessage() setActionModeCallback(textBox) - singleTapSwitch.setOnCheckedChangeListener { _, check -> - gestureHelper.toggleGestureState() - if (check) { - hideKeyboard() + editModeButton.setOnClickListener { + viewModel.setClozeFieldText(textBox.text.toString()) + when (editMode) { + EditMode.SINGLE_TAP -> { + hideKeyboard() + textBox.setText(viewModel.actualClozeFieldText.value) + editMode = EditMode.ADVANCED + viewModel.setEditorMode(EditMode.SINGLE_TAP) + editModeButton.setIconResource(R.drawable.ic_mode_edit_white) + + singleTapLayout.visibility = View.VISIBLE + setupChipGroup(viewModel, clozeChipGroup) + editFieldsLayout?.visibility = View.GONE + } + + EditMode.ADVANCED -> { + viewModel.setEditorMode(EditMode.ADVANCED) + editModeButton.setIconResource(R.drawable.ic_touch) + editMode = EditMode.SINGLE_TAP + + singleTapLayout.visibility = View.GONE + editFieldsLayout?.visibility = View.VISIBLE + } } } } @@ -262,6 +289,20 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect inputMethodManager.hideSoftInputFromWindow(clozeEditTextField.windowToken, 0) } + private fun handleClozeMode(clozeButton: MaterialButton) { + clozeButton.setOnClickListener { + viewModel.toggleClozeMode() + } + lifecycleScope.launch { + viewModel.currentClozeMode.collectLatest { mode -> + when (mode) { + ClozeMode.INCREMENT -> clozeButton.setIconResource(R.drawable.ic_cloze_new_card) + ClozeMode.NO_INCREMENT -> clozeButton.setIconResource(R.drawable.ic_cloze_same_card) + } + } + } + } + /** Set the error message to null when the text is changed in the TextInputEditText **/ private fun enableErrorMessage() { clozeEditTextField.addTextChangedListener(object : TextWatcher { @@ -297,7 +338,6 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect } SaveNoteResult.Success -> { - currentClozeNumber = 0 // Don't show snackbar to avoid blocking parent app showThemedToast(this@InstantNoteEditorActivity, TR.addingAdded(), true) instantAlertDialog.dismiss() @@ -310,11 +350,6 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect } } - override fun onDestroy() { - super.onDestroy() - currentClozeNumber = 0 - } - /** Gets the field content from the editor, and updates the Note **/ private fun extractFieldValues() { val editTextValues = mutableListOf() @@ -323,6 +358,10 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect for (i in 0 until layout.childCount) { val childView = layout.getChildAt(i) + if (childView.id == R.id.single_tap_layout) { + continue + } + if (childView is TextInputLayout) { val text = extractTextFromInputField(childView) Timber.d("String values in field are $text") @@ -430,7 +469,7 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect } viewModel.setDeckId(deck.deckId) // this is called because DeckSpinnerSelection.onDeckAdded doesn't update the list - deckSpinnerSelection!!.initializeNoteEditorDeckSpinner(getColUnsafe) + deckSpinnerSelection!!.initializeNoteEditorDeckSpinner(getColUnsafe, android.R.layout.simple_spinner_item) launchCatchingTask { viewModel.deckId?.let { deckSpinnerSelection!!.selectDeckById(it, false) } } @@ -440,7 +479,6 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect val clozeMenuId = View.generateViewId() textBox.customSelectionActionModeCallback = getActionModeCallback(textBox, clozeMenuId) textBox.customInsertionActionModeCallback = getActionModeCallback(textBox, clozeMenuId) - getActionModeCallback(textBox, clozeMenuId) } private fun getActionModeCallback( @@ -462,7 +500,7 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect convertSelectedTextToCloze( textBox, selectedText, - max(currentClozeNumber, 1) + viewModel.currentClozeNumber ) mode.finish() @@ -494,6 +532,29 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect } } + /** + * Enum representing the modes available for cloze functionality. + */ + enum class ClozeMode { + INCREMENT, + NO_INCREMENT + } + + /** + * This enum class represents the different edit modes available for the user interface element. + */ + enum class EditMode { + /** + * In this mode, a single tap on the text will turn it to cloze + */ + SINGLE_TAP, + + /** + * In this mode, user can edit the text as they want + */ + ADVANCED + } + /** * Enum class that represent the dialog that can be shown when the InstantEditor is initialized * **/ @@ -504,17 +565,4 @@ class InstantNoteEditorActivity : AnkiActivity(), DeckSelectionDialog.DeckSelect /** Indicates that the editor dialog should be shown. **/ SHOW_EDITOR_DIALOG } - - companion object { - // TODO: Should not be global - /** Allows to keep track of the current cloze number, reset to 0 when activity is destroyed **/ - var currentClozeNumber: Int = 0 - } } - -/** - * Encapsulates the shared text data received through Intent - **/ -data class IntentSharedText( - val sharedTextString: String -) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/TextSurroundHelper.kt b/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/TextSurroundHelper.kt deleted file mode 100644 index 1f0e853d7de1..000000000000 --- a/AnkiDroid/src/main/java/com/ichi2/anki/instantnoteeditor/TextSurroundHelper.kt +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2024 Ashish Yadav - * - * 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 . - */ - -package com.ichi2.anki.instantnoteeditor - -import android.view.GestureDetector -import android.view.MotionEvent -import android.widget.EditText -import kotlin.math.max - -/** - * Represents the state of EditText gesture recognition - * - * This data class holds states of gesture recognition for an EditText, - * allowing for clear and concise representation of its state. - */ -data class EditTextGestureState(val isEnabled: Boolean) - -/** - * Helper class to handle gesture recognition for EditText - * - * Facilitates the management of gesture recognition functionality - * for an EditText component. It allows enabling or disabling gesture detection - * based on the provided state, and provides methods for toggling the gesture state. - */ -class EditTextGestureHelper(private val editText: EditText, initialState: EditTextGestureState) { - private var currentState: EditTextGestureState = initialState - - init { - applyState(currentState) - } - - private fun applyState(state: EditTextGestureState) { - if (state.isEnabled) { - enableGesture() - } else { - disableGesture() - } - } - - private fun setupGestureDetection() { - val gestureDetector = - GestureDetector( - editText.context, - object : GestureDetector.SimpleOnGestureListener() { - override fun onSingleTapConfirmed(e: MotionEvent): Boolean { - handleSingleTap(e) - return super.onSingleTapConfirmed(e) - } - } - ) - - editText.setOnTouchListener { _, event -> - gestureDetector.onTouchEvent(event) - editText.onTouchEvent(event) - true - } - - editText.apply { - showSoftInputOnFocus = false - isFocusable = false - isCursorVisible = false - isFocusableInTouchMode = true - } - } - - private fun handleSingleTap(event: MotionEvent) { - singleTap(editText, event) - } - - /** - * Handles a single tap event on the EditText. - * This method is responsible for detecting the tapped word, surrounding it with cloze brackets, - * and updating the EditText with the modified text. - * - * @param editText The EditText where the tap event occurred. - * @param event The MotionEvent representing the tap event. - */ - private fun singleTap(editText: EditText, event: MotionEvent) { - val layout = editText.layout - val x = event.x.toInt() - val y = event.y.toInt() - - val line = layout.getLineForVertical(y) - val offset = layout.getOffsetForHorizontal(line, x.toFloat()) - - val text = editText.text.toString() - val start = findWordStart(text, offset) - val end = findWordEnd(text, offset) - - val selectedWord = text.substring(start, end) - InstantNoteEditorActivity.currentClozeNumber = max(InstantNoteEditorActivity.currentClozeNumber, 1) - val newText = buildString { - append(text.substring(0, start)) - append("{{c${InstantNoteEditorActivity.currentClozeNumber}::$selectedWord}}") - append(text.substring(end)) - } - editText.setText(newText) - } - - private fun findWordStart(text: String, offset: Int): Int { - var start = offset - while (start > 0 && !text[start - 1].isWhitespace()) { - start-- - } - return start - } - - private fun findWordEnd(text: String, offset: Int): Int { - var end = offset - while (end < text.length && !text[end].isWhitespace()) { - end++ - } - return end - } - - private fun enableGesture() { - setupGestureDetection() - } - - private fun disableGesture() { - editText.apply { - setOnTouchListener(null) - isFocusable = true - isFocusableInTouchMode = true - showSoftInputOnFocus = true - isCursorVisible = true - } - } - - fun toggleGestureState() { - currentState = EditTextGestureState(!currentState.isEnabled) - applyState(currentState) - } -} diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/preferences/DevOptionsFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/preferences/DevOptionsFragment.kt index 3b6fb58e2f0c..80750f4fe131 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/preferences/DevOptionsFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/preferences/DevOptionsFragment.kt @@ -86,7 +86,7 @@ class DevOptionsFragment : SettingsFragment() { // Instant Editor requirePreference(R.string.pref_open_instant_editor).setOnPreferenceClickListener { val intent = Intent(activity, InstantNoteEditorActivity::class.java).apply { - putExtra("extra_text_key", "Hello developer, this a test sentence. You can test turning text to cloze here") + putExtra("extra_text_key", "Hello developer this is a test sentence. You can test turning text to cloze here") } startActivity(intent) false diff --git a/AnkiDroid/src/main/res/layout/instant_editor_dialog.xml b/AnkiDroid/src/main/res/layout/instant_editor_dialog.xml index 9d461c66e8b2..0841d76d4135 100644 --- a/AnkiDroid/src/main/res/layout/instant_editor_dialog.xml +++ b/AnkiDroid/src/main/res/layout/instant_editor_dialog.xml @@ -17,6 +17,7 @@ @@ -51,17 +52,16 @@ android:id="@+id/note_deck_spinner" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_weight="1" app:popupTheme="@style/ActionBar.Popup" /> + app:icon="@drawable/ic_mode_edit_white" /> + +
+ + + + + + + + + + + + + - - Cloze Type Note Required
No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/instanteditor/InstantEditorViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/instanteditor/InstantEditorViewModelTest.kt index 3c438741b5a0..7b425fe886f4 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/instanteditor/InstantEditorViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/instanteditor/InstantEditorViewModelTest.kt @@ -23,7 +23,6 @@ import com.ichi2.anki.RobolectricTest import com.ichi2.anki.instantnoteeditor.InstantEditorViewModel import com.ichi2.anki.instantnoteeditor.InstantNoteEditorActivity import com.ichi2.anki.instantnoteeditor.SaveNoteResult -import com.ichi2.libanki.removeNotetype import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test @@ -87,6 +86,85 @@ class InstantEditorViewModelTest : RobolectricTest() { assertTrue(result is SaveNoteResult.Warning) } + @Test + fun `buildClozeText handles punctuation at end`() = runViewModelTest { + val text = "test," + val result = buildClozeText(text) + + assertEquals("{{c1::test}},", result) + } + + @Test + fun `buildClozeText handles cloze punctuation at end`() = runViewModelTest { + val text = "{{c1::test}}," + val result = buildClozeText(text) + + assertEquals("test,", result) + } + + @Test + fun buildClozeTextTest() = runViewModelTest { + val text = "test" + val result = buildClozeText(text) + + assertEquals("{{c1::test}}", result) + } + + @Test + fun `buildClozeText handles undo word`() = runViewModelTest { + val text = "{{c1::Word}}" + val result = buildClozeText(text) + + assertEquals("Word", result) + } + + @Test + fun testExtractWordsIncludingClozes() = runViewModelTest { + val sentence = "This is a {{c1::test}} sentence with {{c2::multiple}} clozes." + setClozeFieldText(sentence) + val expectedWords = listOf("This", "is", "a", "{{c1::test}}", "sentence", "with", "{{c2::multiple}}", "clozes.") + val extractedWords = getWordsFromFieldText() + assertEquals(expectedWords, extractedWords) + } + + @Test + fun testExtractWordsIncludingPunctuations() = runViewModelTest { + val sentence = "This is a {{c1::test}}!! sentence with {{c2::multiple}} clozes?" + setClozeFieldText(sentence) + val expectedWords = listOf("This", "is", "a", "{{c1::test}}!!", "sentence", "with", "{{c2::multiple}}", "clozes?") + val extractedWords = getWordsFromFieldText() + assertEquals(expectedWords, extractedWords) + } + + @Test + fun testGetCleanClozeWords() = runViewModelTest { + val testCases = listOf( + "{{c1::word}}" to "word", + "{{c2::another}}" to "another", + "{{c4::help}}!!" to "help!!", + "no cloze" to "no cloze" + ) + + testCases.forEach { (input, expected) -> + val cleanedWord = getCleanClozeWords(input) + assertEquals(expected, cleanedWord) + } + } + + @Test + fun testSwitchingBetweenEditModes() = runViewModelTest { + val word = "Word!" + val expectedCloze = "{{c1::Word}}!" + + val result = buildClozeText(word) + + assertEquals(expectedCloze, result) + + val cleanWord = getCleanClozeWords(expectedCloze) + + assertEquals(word, cleanWord) + } + private fun runViewModelTest( initViewModel: () -> InstantEditorViewModel = { InstantEditorViewModel() }, testBody: suspend InstantEditorViewModel.() -> Unit From a569c572d67c7ca2983a8b58e269769751aa4ca9 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Mon, 10 Jun 2024 19:07:54 +0100 Subject: [PATCH 075/138] fix: AppWidgetManager can be null On a Supernote A5X, `AppWidgetManager.getInstance(context)` returns `null` https://www.reddit.com/r/Supernote/comments/1dcqk47/comment/l7znpix/ --- .../com/ichi2/widget/AnkiDroidWidgetSmall.kt | 8 +-- .../ichi2/widget/WidgetPermissionReceiver.kt | 3 +- .../main/java/com/ichi2/widget/WidgetUtils.kt | 30 ++++++++++ .../widget/WidgetUtilsIntegrationTest.kt | 56 +++++++++++++++++++ 4 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 AnkiDroid/src/main/java/com/ichi2/widget/WidgetUtils.kt create mode 100644 AnkiDroid/src/test/java/com/ichi2/widget/WidgetUtilsIntegrationTest.kt diff --git a/AnkiDroid/src/main/java/com/ichi2/widget/AnkiDroidWidgetSmall.kt b/AnkiDroid/src/main/java/com/ichi2/widget/AnkiDroidWidgetSmall.kt index 6d2b20bbf460..dbea6971f6bb 100644 --- a/AnkiDroid/src/main/java/com/ichi2/widget/AnkiDroidWidgetSmall.kt +++ b/AnkiDroid/src/main/java/com/ichi2/widget/AnkiDroidWidgetSmall.kt @@ -73,16 +73,16 @@ class AnkiDroidWidgetSmall : AppWidgetProvider() { /** The cached number of total due cards. */ private var dueCardsCount = 0 fun doUpdate(context: Context) { - AppWidgetManager.getInstance(context) - .updateAppWidget(ComponentName(context, AnkiDroidWidgetSmall::class.java), buildUpdate(context, true)) + val appWidgetManager = getAppWidgetManager(context) ?: return + appWidgetManager.updateAppWidget(ComponentName(context, AnkiDroidWidgetSmall::class.java), buildUpdate(context, true)) } @Deprecated("Implement onStartCommand(Intent, int, int) instead.") // TODO override fun onStart(intent: Intent, startId: Int) { Timber.i("SmallWidget: OnStart") + val manager = getAppWidgetManager(this) ?: return val updateViews = buildUpdate(this, true) val thisWidget = ComponentName(this, AnkiDroidWidgetSmall::class.java) - val manager = AppWidgetManager.getInstance(this) manager.updateAppWidget(thisWidget, updateViews) } @@ -180,7 +180,7 @@ class AnkiDroidWidgetSmall : AppWidgetProvider() { private var mMountReceiver: BroadcastReceiver? = null private var remounted = false private fun updateWidgetDimensions(context: Context, updateViews: RemoteViews, cls: Class<*>) { - val manager = AppWidgetManager.getInstance(context) + val manager = getAppWidgetManager(context) ?: return val ids = manager.getAppWidgetIds(ComponentName(context, cls)) for (id in ids) { val scale = context.resources.displayMetrics.density diff --git a/AnkiDroid/src/main/java/com/ichi2/widget/WidgetPermissionReceiver.kt b/AnkiDroid/src/main/java/com/ichi2/widget/WidgetPermissionReceiver.kt index 97c36cfc0af9..2f77b7b33ba7 100644 --- a/AnkiDroid/src/main/java/com/ichi2/widget/WidgetPermissionReceiver.kt +++ b/AnkiDroid/src/main/java/com/ichi2/widget/WidgetPermissionReceiver.kt @@ -17,7 +17,6 @@ package com.ichi2.widget -import android.appwidget.AppWidgetManager import android.content.BroadcastReceiver import android.content.ComponentName import android.content.Context @@ -32,7 +31,7 @@ class WidgetPermissionReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (IntentHandler.grantedStoragePermissions(context, showToast = false)) { - val appWidgetManager = AppWidgetManager.getInstance(context) + val appWidgetManager = getAppWidgetManager(context) ?: return val widgetIds = appWidgetManager.getAppWidgetIds(ComponentName(context, AddNoteWidget::class.java)) AddNoteWidget.updateWidgets(context, appWidgetManager, widgetIds) } diff --git a/AnkiDroid/src/main/java/com/ichi2/widget/WidgetUtils.kt b/AnkiDroid/src/main/java/com/ichi2/widget/WidgetUtils.kt new file mode 100644 index 000000000000..d5d985459a19 --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/widget/WidgetUtils.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 David Allison + * + * 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 . + */ + +package com.ichi2.widget + +import android.appwidget.AppWidgetManager +import android.content.Context + +/** + * @return An [AppWidgetManager] for the provided context, or `null` + * + * @see AppWidgetManager.getInstance + */ +// The call returns null on a Supernote A5X, but as the underlying platform call is in Java, +// the result is assumed to be non-null in Kotlin +fun getAppWidgetManager(context: Context): AppWidgetManager? = + AppWidgetManager.getInstance(context) diff --git a/AnkiDroid/src/test/java/com/ichi2/widget/WidgetUtilsIntegrationTest.kt b/AnkiDroid/src/test/java/com/ichi2/widget/WidgetUtilsIntegrationTest.kt new file mode 100644 index 000000000000..5acb13053fc5 --- /dev/null +++ b/AnkiDroid/src/test/java/com/ichi2/widget/WidgetUtilsIntegrationTest.kt @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 David Allison + * + * 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 . + */ + +package com.ichi2.widget + +import android.appwidget.AppWidgetManager +import android.content.Intent +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.ichi2.anki.DeckPicker +import com.ichi2.anki.RobolectricTest +import io.mockk.every +import io.mockk.mockkStatic +import io.mockk.unmockkStatic +import org.junit.AfterClass +import org.junit.BeforeClass +import org.junit.Test +import org.junit.runner.RunWith + +/** @see getAppWidgetManager */ +@RunWith(AndroidJUnit4::class) +class WidgetUtilsIntegrationTest : RobolectricTest() { + // on a Supernote A5X, AppWidgetManager.getInstance(context) returns null + @Test + fun `app runs with no widget manager`() { + super.startRegularActivity() // WARN: This didn't crash before fixes applied + WidgetPermissionReceiver().onReceive(targetContext, Intent()) + } + + companion object { + @BeforeClass + @JvmStatic + fun setUpClass() { + mockkStatic(AppWidgetManager::class) + every { AppWidgetManager.getInstance(any()) } answers { null } + } + + @AfterClass + @JvmStatic + fun tearDownClass() { + unmockkStatic(AppWidgetManager::class) + } + } +} From 840f46b14c649f60c993d5e6820ec5a3ab9094c2 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Wed, 12 Jun 2024 21:46:17 +0100 Subject: [PATCH 076/138] feat(col): expose browser table methods https://github.com/ankitects/anki/blob/33a923797afc9655c3b4f79847e1705a1f998d03/pylib/anki/collection.py https://github.com/ankitects/anki/blob/33a923797afc9655c3b4f79847e1705a1f998d03/pylib/anki/browser.py Prep for Issue 11889 --- .../java/com/ichi2/libanki/BrowserConfig.kt | 54 +++++++++++ .../main/java/com/ichi2/libanki/Collection.kt | 94 +++++++++++++++---- .../java/com/ichi2/libanki/CollectionTest.kt | 61 ++++++++++++ 3 files changed, 192 insertions(+), 17 deletions(-) create mode 100644 AnkiDroid/src/main/java/com/ichi2/libanki/BrowserConfig.kt diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/BrowserConfig.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/BrowserConfig.kt new file mode 100644 index 000000000000..1e400b838955 --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/BrowserConfig.kt @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 David Allison + * + * 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 . + * + * This file incorporates code under the following license + * https://github.com/ankitects/anki/blob/33a923797afc9655c3b4f79847e1705a1f998d03/pylib/anki/browser.py + * + * Copyright: Ankitects Pty Ltd and contributors + * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html + */ + +package com.ichi2.libanki + +import com.ichi2.libanki.utils.LibAnkiAlias + +object BrowserConfig { + const val ACTIVE_CARD_COLUMNS_KEY = "activeCols" + const val ACTIVE_NOTE_COLUMNS_KEY = "activeNoteCols" + const val CARDS_SORT_COLUMN_KEY = "sortType" + const val NOTES_SORT_COLUMN_KEY = "noteSortType" + const val CARDS_SORT_BACKWARDS_KEY = "sortBackwards" + const val NOTES_SORT_BACKWARDS_KEY = "browserNoteSortBackwards" + + @LibAnkiAlias("active_columns_key") + fun activeColumnsKey(isNotesMode: Boolean): String = + if (isNotesMode) ACTIVE_NOTE_COLUMNS_KEY else ACTIVE_CARD_COLUMNS_KEY + + @LibAnkiAlias("sort_column_key") + fun sortColumnKey(isNotesMode: Boolean): String = + if (isNotesMode) NOTES_SORT_COLUMN_KEY else CARDS_SORT_COLUMN_KEY + + @LibAnkiAlias("sort_backwards_key") + fun sortBackwardsKey(isNotesMode: Boolean): String = + if (isNotesMode) NOTES_SORT_BACKWARDS_KEY else CARDS_SORT_BACKWARDS_KEY +} + +object BrowserDefaults { + @LibAnkiAlias("CARD_COLUMNS") + val CARD_COLUMNS: List = listOf("noteFld", "template", "cardDue", "deck") + + @LibAnkiAlias("NOTE_COLUMNS") + val NOTE_COLUMNS: List = listOf("noteFld", "note", "template", "noteTags") +} diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt index de7dd4e56dae..ff1ca120d29f 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt @@ -1,19 +1,25 @@ -/**************************************************************************************** - * Copyright (c) 2011 Norbert Nagold * - * Copyright (c) 2012 Kostas Spyropoulos * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General private 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 private License for more details. * - * * - * You should have received a copy of the GNU General private License along with * - * this program. If not, see . * - ****************************************************************************************/ +/* + * Copyright (c) 2011 Norbert Nagold + * Copyright (c) 2012 Kostas Spyropoulos + * Copyright (c) 2024 David Allison + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General private 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 private License for more details. + * + * You should have received a copy of the GNU General private License along with + * this program. If not, see . + * This file incorporates code under the following license + * https://github.com/ankitects/anki/blob/33a923797afc9655c3b4f79847e1705a1f998d03/pylib/anki/browser.py + * + * Copyright: Ankitects Pty Ltd and contributors + * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html + */ // "FunctionName": many libAnki functions used to have leading _s @file:Suppress("FunctionName") @@ -29,7 +35,8 @@ import anki.collection.OpChangesWithCount import anki.config.ConfigKey import anki.config.Preferences import anki.config.copy -import anki.config.preferences +import anki.search.BrowserColumns +import anki.search.BrowserRow import anki.search.SearchNode import anki.sync.SyncAuth import anki.sync.SyncStatusResponse @@ -40,6 +47,7 @@ import com.ichi2.libanki.exception.ConfirmModSchemaException import com.ichi2.libanki.exception.InvalidSearchException import com.ichi2.libanki.sched.DummyScheduler import com.ichi2.libanki.sched.Scheduler +import com.ichi2.libanki.utils.LibAnkiAlias import com.ichi2.libanki.utils.NotInLibAnki import com.ichi2.libanki.utils.TimeManager import com.ichi2.utils.KotlinCleanup @@ -440,11 +448,63 @@ class Collection( return sortedResultList.map { it.id } } + @LibAnkiAlias("find_and_replace") @RustCleanup("Calling code should handle returned OpChanges") fun findReplace(nids: List, src: String, dst: String, regex: Boolean = false, field: String? = null, fold: Boolean = true): Int { return backend.findAndReplace(nids, src, dst, regex, !fold, field ?: "").count } + /* Browser Table */ + + @LibAnkiAlias("all_browser_columns") + fun allBrowserColumns(): List = backend.allBrowserColumns() + + @LibAnkiAlias("get_browser_column") + fun getBrowserColumn(key: String): BrowserColumns.Column? { + for (column in backend.allBrowserColumns()) { + if (column.key == key) { + return column + } + } + return null + } + + // consider changing implementation to return protobuf directly + @LibAnkiAlias("browser_row_for_id") + @Deprecated("not implemented", replaceWith = ReplaceWith("nothing")) + fun browserRowForId(id: Long): BrowserRow = TODO() + + /** Return the stored card column names and ensure the backend columns are set and in sync. */ + @LibAnkiAlias("load_browser_card_columns") + fun loadBrowserCardColumns(): List { + val columns = config.get>(BrowserConfig.ACTIVE_CARD_COLUMNS_KEY, BrowserDefaults.CARD_COLUMNS)!! + backend.setActiveBrowserColumns(columns) + return columns + } + + @LibAnkiAlias("set_browser_card_columns") + fun setBrowserCardColumns(columns: List) { + config.set(BrowserConfig.ACTIVE_CARD_COLUMNS_KEY, columns) + backend.setActiveBrowserColumns(columns) + } + + /** Return the stored note column names and ensure the backend columns are set and in sync. */ + @LibAnkiAlias("load_browser_note_columns") + fun loadBrowserNoteColumns(): List { + val columns = config.get>( + BrowserConfig.ACTIVE_NOTE_COLUMNS_KEY, + BrowserDefaults.NOTE_COLUMNS + )!! + backend.setActiveBrowserColumns(columns) + return columns + } + + @LibAnkiAlias("set_browser_note_columns") + fun setBrowserNoteColumns(columns: List) { + config.set(BrowserConfig.ACTIVE_NOTE_COLUMNS_KEY, columns) + backend.setActiveBrowserColumns(columns) + } + /* Stats ******************************************************************** *************************** */ diff --git a/AnkiDroid/src/test/java/com/ichi2/libanki/CollectionTest.kt b/AnkiDroid/src/test/java/com/ichi2/libanki/CollectionTest.kt index e46a96054e2a..52b395eaee39 100644 --- a/AnkiDroid/src/test/java/com/ichi2/libanki/CollectionTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/libanki/CollectionTest.kt @@ -21,6 +21,9 @@ import com.ichi2.testutils.JvmTest import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers import org.hamcrest.Matchers.equalTo +import org.hamcrest.Matchers.hasSize +import org.hamcrest.Matchers.not +import org.hamcrest.Matchers.nullValue import org.junit.Assert.* import org.junit.Ignore import org.junit.Test @@ -206,4 +209,62 @@ class CollectionTest : JvmTest() { val cid = addNoteUsingBasicModel("foo", "bar").firstCard().id assertEquals(ArrayList(setOf(cid)), col.filterToValidCards(longArrayOf(cid, cid + 1))) } + + @Test + fun `default card columns`() { + assertThat( + col.loadBrowserCardColumns(), + equalTo( + listOf("noteFld", "template", "cardDue", "deck") + ) + ) + } + + @Test + fun `default note columns`() { + assertThat( + col.loadBrowserNoteColumns(), + equalTo( + listOf("noteFld", "note", "template", "noteTags") + ) + ) + } + + @Test + fun `set note columns`() { + col.setBrowserNoteColumns(listOf("noteFld")) + + assertThat( + col.loadBrowserNoteColumns(), + equalTo( + listOf("noteFld") + ) + ) + } + + @Test + fun `set card columns`() { + col.setBrowserCardColumns(listOf("question")) + + assertThat( + col.loadBrowserCardColumns(), + equalTo( + listOf("question") + ) + ) + } + + @Test + fun `get browser column`() { + kotlin.test.assertNotNull(col.getBrowserColumn("question")).also { + assertThat(it.cardsModeLabel, equalTo("Question")) + } + + assertThat(col.getBrowserColumn("invalid"), nullValue()) + } + + @Test + fun `get all columns`() { + assertThat(col.allBrowserColumns(), not(hasSize(0))) + } } From f2cb6841749aed2964caf7fe7a0352a9966d57d0 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Fri, 14 Jun 2024 21:27:17 +0100 Subject: [PATCH 077/138] refactor: remove unused browser columns Defined in neither * COLUMN1_KEYS * COLUMN2_KEYS These define the order in R.array.browser_column1_headings R.array.browser_column2_headings So they are unused ID matched the `else` case in the `when` for CardCache, and that returned `null` --- AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt | 3 --- .../src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt index e8db2b486827..5657a284f2ff 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt @@ -1920,9 +1920,6 @@ open class CardBrowser : fun getColumnHeaderText(key: CardBrowserColumn?): String? { return when (key) { - CardBrowserColumn.FLAGS -> Integer.valueOf(card.userFlag()).toString() - CardBrowserColumn.SUSPENDED -> if (card.queue == Consts.QUEUE_TYPE_SUSPENDED) "True" else "False" - CardBrowserColumn.MARKED -> if (isMarked(col, card.note(col))) "marked" else null CardBrowserColumn.SFLD -> card.note(col).sFld(col) CardBrowserColumn.DECK -> col.decks.name(card.did) CardBrowserColumn.TAGS -> card.note(col).stringTags(col) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt index a9b12a0083ed..ad490c486e06 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt @@ -17,7 +17,7 @@ package com.ichi2.anki.browser enum class CardBrowserColumn { - QUESTION, ANSWER, FLAGS, SUSPENDED, MARKED, SFLD, DECK, TAGS, ID, CARD, DUE, EASE, CHANGED, CREATED, EDITED, INTERVAL, LAPSES, NOTE_TYPE, REVIEWS; + QUESTION, ANSWER, SFLD, DECK, TAGS, CARD, DUE, EASE, CHANGED, CREATED, EDITED, INTERVAL, LAPSES, NOTE_TYPE, REVIEWS; companion object { From e76f022ae8d2b44b0fa6dae34aa1a13676ef4992 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Fri, 14 Jun 2024 21:12:08 +0100 Subject: [PATCH 078/138] chore: map CardBrowserColumn to backend column We are going to remove this class and use the backend for both the column definitions and the retrieval of data But before we do this, we want to map from a complex index-based collection to the Anki Backend Column keys, so users do not lose their settings in the migration This change verifies that the columns are mapped and implemented the same way in the new backend --- .../ichi2/anki/browser/CardBrowserColumn.kt | 82 ++++++++++++++- .../anki/browser/CardBrowserColumnTest.kt | 99 +++++++++++++++++++ 2 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnTest.kt diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt index ad490c486e06..383947074ee4 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt @@ -16,8 +16,83 @@ package com.ichi2.anki.browser -enum class CardBrowserColumn { - QUESTION, ANSWER, SFLD, DECK, TAGS, CARD, DUE, EASE, CHANGED, CREATED, EDITED, INTERVAL, LAPSES, NOTE_TYPE, REVIEWS; +import anki.search.BrowserColumns +import com.ichi2.anki.CardBrowser +import com.ichi2.anki.R +import com.ichi2.anki.browser.CardBrowserViewModel.Companion.DISPLAY_COLUMN_1_KEY +import com.ichi2.anki.browser.CardBrowserViewModel.Companion.DISPLAY_COLUMN_2_KEY +import net.ankiweb.rsdroid.Backend + +/** + * A column available in the [browser][CardBrowser] + * + * @see COLUMN1_KEYS: from preference [DISPLAY_COLUMN_1_KEY] to [R.array.browser_column1_headings] + * @see COLUMN2_KEYS: from preference [DISPLAY_COLUMN_2_KEY] to [R.array.browser_column2_headings] + * @see CardBrowser.CardCache.getColumnHeaderText - how columns are rendered + * + * @param ankiColumnKey The key used in [Backend.setActiveBrowserColumns] + */ +enum class CardBrowserColumn(val ankiColumnKey: String) { + /** Rendered front side of the first card of the note */ + QUESTION("question"), + + /** Rendered back side of the first card of the note */ + ANSWER("answer"), + + /** The value of the field marked as "Sort by this field in the Browser" */ + SFLD("noteFld"), + + /** + * Cards -> The deck which contains the card + * Notes -> Either the deck containing the card, or `(n)`, where n is the number of + * distinct decks + */ + DECK("deck"), + + /** A list of tags for the note */ + TAGS("noteTags"), + + /** + * Cards -> Card Type + * Notes -> Cards (card count) + */ + CARD("template"), + DUE("cardDue"), + + /** + * Cards -> Ease + * Notes -> Average Ease + */ + EASE("cardEase"), + + /** + * Cards -> Timestamp the card was modified + * Notes -> Most recent timestamp a card of the note was modified + */ + CHANGED("cardMod"), + + /** + * Timestamp the note was created + */ + CREATED("noteCrt"), + + /** + * Timestamp the note was last changed + */ + EDITED("noteMod"), + + /** + * Cards -> Interval + * Notes -> Interval + */ + INTERVAL("cardIvl"), + LAPSES("cardLapses"), + + /** + * The name of the note type `Basic (and reversed card)` + */ + NOTE_TYPE("note"), + REVIEWS("cardReps"); companion object { @@ -28,3 +103,6 @@ enum class CardBrowserColumn { val COLUMN2_KEYS = arrayOf(ANSWER, CARD, DECK, NOTE_TYPE, QUESTION, TAGS, LAPSES, REVIEWS, INTERVAL, EASE, DUE, CHANGED, CREATED, EDITED) } } + +fun List.find(column: CardBrowserColumn): BrowserColumns.Column = + this.first { it.key == column.ankiColumnKey } diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnTest.kt new file mode 100644 index 000000000000..0aff7a4d587e --- /dev/null +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnTest.kt @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2024 David Allison + * + * 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 . + */ + +package com.ichi2.anki.browser + +import com.ichi2.anki.CardBrowser +import com.ichi2.anki.browser.CardBrowserColumn.CHANGED +import com.ichi2.anki.browser.CardBrowserColumn.CREATED +import com.ichi2.anki.browser.CardBrowserColumn.DUE +import com.ichi2.anki.browser.CardBrowserColumn.EDITED +import com.ichi2.anki.model.CardsOrNotes +import com.ichi2.testutils.JvmTest +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo +import org.hamcrest.Matchers.`in` +import org.hamcrest.Matchers.not +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.ParameterizedRobolectricTestRunner +import timber.log.Timber +import kotlin.test.assertNotNull + +/** @see CardBrowserColumn */ +@RunWith(ParameterizedRobolectricTestRunner::class) +class CardBrowserColumnTest : JvmTest() { + + companion object { + @ParameterizedRobolectricTestRunner.Parameters(name = "{0}") + @JvmStatic // required for initParameters + fun initParameters(): Collection> { + return CardBrowserColumn.entries + .map { arrayOf(it) } + } + } + + @ParameterizedRobolectricTestRunner.Parameter + @JvmField // required for Parameter + var columnParam: CardBrowserColumn? = null + private val column get() = columnParam!! + + @Test + fun ensureAllColumnsMapped() { + val collectionColumns = col.backend.allBrowserColumns() + Timber.w("%s", collectionColumns.joinToString { it.key }) + assertNotNull(collectionColumns.find(column)) + } + + @Test + fun `cards - ensure old values match backend values`() { + with(col) { CardsOrNotes.CARDS.saveToCollection() } + `ensure old values match backend values`(CardsOrNotes.CARDS) + } + + @Test + fun `notes - ensure old values match backend values`() { + with(col) { CardsOrNotes.NOTES.saveToCollection() } + `ensure old values match backend values`(CardsOrNotes.NOTES) + } + + private fun `ensure old values match backend values`(cardsOrNotes: CardsOrNotes) { + // dates seem correct - we don't currently display minutes + assumeThat(column, not(`in`(listOf(CHANGED, CREATED, EDITED)))) + + val note = addNoteUsingBasicModel() + val cid = note.cids()[0] + val nid = note.id + + var oldData = CardBrowser.CardCache(cid, col, 0, cardsOrNotes) + .getColumnHeaderText(column) + + val newData = column.let { + col.backend.setActiveBrowserColumns(listOf(it.ankiColumnKey)) + val rowId = if (cardsOrNotes == CardsOrNotes.CARDS) cid else nid + col.backend.browserRowForId(rowId).getCells(0).text + } + + if (column == DUE) { + oldData = when (cardsOrNotes) { + CardsOrNotes.CARDS -> "New #\u2068${oldData}\u2069" + CardsOrNotes.NOTES -> "" + } + } + + assertThat(newData, equalTo(oldData)) + } +} From 6c5e46ad21bb85053fe2eb460ad9f4c89c544623 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Fri, 14 Jun 2024 21:58:21 +0100 Subject: [PATCH 079/138] docs: ensure BrowserColumns are documented --- .idea/dictionaries/anki.xml | 2 + .../ichi2/anki/browser/CardBrowserColumn.kt | 21 +++++++++- .../browser/CardBrowserColumnNonParamTest.kt | 39 +++++++++++++++++++ .../anki/browser/CardBrowserColumnTest.kt | 16 ++++++++ 4 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnNonParamTest.kt diff --git a/.idea/dictionaries/anki.xml b/.idea/dictionaries/anki.xml index b9fabcf1c6b3..981f71fcc504 100644 --- a/.idea/dictionaries/anki.xml +++ b/.idea/dictionaries/anki.xml @@ -2,6 +2,7 @@ Ankitects + FSRS Fsrs NOTEEDITOR afmt @@ -99,6 +100,7 @@ relrn replaybutton resched + retrievability revlog revlogs rlim diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt index 383947074ee4..ed0e078a4994 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt @@ -92,7 +92,26 @@ enum class CardBrowserColumn(val ankiColumnKey: String) { * The name of the note type `Basic (and reversed card)` */ NOTE_TYPE("note"), - REVIEWS("cardReps"); + REVIEWS("cardReps"), + + /** + * The inherent complexity associated with a particular memory. + * Used in FSRS, blank if using SM-2 + */ + FSRS_DIFFICULTY("difficulty"), + + /** + * The probability of recalling a specific memory at a given moment. + * Used in FSRS, blank if using SM-2 + */ + FSRS_RETRIEVABILITY("retrievability"), + + /** + * The time required for the probability of recall for a particular memory to decline from + * 100% to 90%. + * Used in FSRS, blank if using SM-2 + */ + FSRS_STABILITY("stability"); companion object { diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnNonParamTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnNonParamTest.kt new file mode 100644 index 000000000000..b5ef94ac9e49 --- /dev/null +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnNonParamTest.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 David Allison + * + * 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 . + */ + +package com.ichi2.anki.browser + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.ichi2.testutils.JvmTest +import org.hamcrest.Matchers.not +import org.junit.Test +import org.junit.runner.RunWith +import kotlin.test.assertContentEquals + +/** @see CardBrowserColumn */ +@RunWith(AndroidJUnit4::class) +class CardBrowserColumnNonParamTest : JvmTest() { + + @Test + fun `all keys are documented`() { + // meta test - the column keys aren't documented well + // this ensures the columns are greppable in the code + val ankiColumnKeys = col.backend.allBrowserColumns().map { it.key }.sorted() + val ourKeys = CardBrowserColumn.entries.map { it.ankiColumnKey }.sorted() + + assertContentEquals(ankiColumnKeys, ourKeys) + } +} diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnTest.kt index 0aff7a4d587e..4cdf3bfdf6a2 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnTest.kt @@ -21,6 +21,9 @@ import com.ichi2.anki.browser.CardBrowserColumn.CHANGED import com.ichi2.anki.browser.CardBrowserColumn.CREATED import com.ichi2.anki.browser.CardBrowserColumn.DUE import com.ichi2.anki.browser.CardBrowserColumn.EDITED +import com.ichi2.anki.browser.CardBrowserColumn.FSRS_DIFFICULTY +import com.ichi2.anki.browser.CardBrowserColumn.FSRS_RETRIEVABILITY +import com.ichi2.anki.browser.CardBrowserColumn.FSRS_STABILITY import com.ichi2.anki.model.CardsOrNotes import com.ichi2.testutils.JvmTest import org.hamcrest.MatcherAssert.assertThat @@ -73,6 +76,19 @@ class CardBrowserColumnTest : JvmTest() { private fun `ensure old values match backend values`(cardsOrNotes: CardsOrNotes) { // dates seem correct - we don't currently display minutes assumeThat(column, not(`in`(listOf(CHANGED, CREATED, EDITED)))) + // FSRS is not implemented + assumeThat( + column, + not( + `in`( + listOf( + FSRS_DIFFICULTY, + FSRS_RETRIEVABILITY, + FSRS_STABILITY + ) + ) + ) + ) val note = addNoteUsingBasicModel() val cid = note.cids()[0] From dcb10769b16c72f52c4191d35f36a494be46fc3a Mon Sep 17 00:00:00 2001 From: abdelrahmanesam Date: Fri, 14 Jun 2024 17:25:25 +0300 Subject: [PATCH 080/138] extract magic numbers to version catalog --- AnkiDroid/build.gradle | 6 +++--- api/build.gradle.kts | 4 ++-- common/build.gradle.kts | 4 ++-- gradle/libs.versions.toml | 3 +++ testlib/build.gradle.kts | 4 ++-- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/AnkiDroid/build.gradle b/AnkiDroid/build.gradle index 8a4a04fd5ea8..5487f9db74ad 100644 --- a/AnkiDroid/build.gradle +++ b/AnkiDroid/build.gradle @@ -35,7 +35,7 @@ static def gitCommitHash() { android { namespace "com.ichi2.anki" - compileSdk 34 // change api compileSdk at the same time + compileSdk libs.versions.compileSdk.get().toInteger() buildFeatures { buildConfig = true @@ -76,9 +76,9 @@ android { // needed for upgrades to be offered correctly. versionCode=21900104 versionName="2.19alpha4" - minSdk 23 // also in testlib/build.gradle.kts + minSdk libs.versions.minSdk.get().toInteger() // After #13695: change .tests_emulator.yml - targetSdk 33 // also in [api|testlib]/build.gradle.kts and ../robolectricDownloader.gradle + targetSdk libs.versions.targetSdk.get().toInteger() testApplicationId "com.ichi2.anki.tests" vectorDrawables.useSupportLibrary = true testInstrumentationRunner 'com.ichi2.testutils.NewCollectionPathTestRunner' diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 35408a5bac84..b7508fe0a42f 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -16,14 +16,14 @@ kotlin { android { namespace = "com.ichi2.anki.api" - compileSdk = 34 + compileSdk = libs.versions.compileSdk.get().toInt() buildFeatures { buildConfig = true } defaultConfig { - minSdk = 16 + minSdk = libs.versions.minSdk.get().toInt() buildConfigField( "String", "READ_WRITE_PERMISSION", diff --git a/common/build.gradle.kts b/common/build.gradle.kts index f17ac924a2d3..90d195acdfb9 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -8,10 +8,10 @@ android { // but we can define files in 'com.ichi2.anki' inside 'common' // even with this namespace namespace = "com.ichi2.anki.common" - compileSdk = 34 + compileSdk = libs.versions.compileSdk.get().toInt() defaultConfig { - minSdk = 23 + minSdk = libs.versions.minSdk.get().toInt() testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 44b191042df5..20eadb840748 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,4 +1,7 @@ [versions] +compileSdk = "34" +minSdk = "23" # also in testlib/build.gradle.kts +targetSdk = "33" # also in ../robolectricDownloader.gradle acra = '5.11.3' amazonappstorepublisher = "0.1.0" androidGradlePlugin = "8.4.1" diff --git a/testlib/build.gradle.kts b/testlib/build.gradle.kts index b205abed06c0..ddb7a479190b 100644 --- a/testlib/build.gradle.kts +++ b/testlib/build.gradle.kts @@ -5,10 +5,10 @@ plugins { android { namespace = "com.ichi2.anki.testlib" - compileSdk = 34 + compileSdk = libs.versions.compileSdk.get().toInt() defaultConfig { - minSdk = 23 + minSdk = libs.versions.minSdk.get().toInt() } flavorDimensions += "appStore" From 8ea8704605e877414ee90a009d613d4de9de3691 Mon Sep 17 00:00:00 2001 From: AnkiDroid Translations Date: Sun, 16 Jun 2024 08:10:42 +0000 Subject: [PATCH 081/138] Updated strings from Crowdin --- AnkiDroid/src/main/res/values-af/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-am/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ar/01-core.xml | 2 +- AnkiDroid/src/main/res/values-ar/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-az/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-be/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-bg/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-bn/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ca/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ckb/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-cs/03-dialogs.xml | 3 +-- AnkiDroid/src/main/res/values-cs/04-network.xml | 2 +- AnkiDroid/src/main/res/values-da/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-de/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-el/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-eo/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-et/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-eu/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-fa/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-fi/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-fil/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-fr/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-fy/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ga/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-gl/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-got/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-gu/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-gu/04-network.xml | 6 +++--- AnkiDroid/src/main/res/values-heb/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-hi/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-hr/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-hu/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-hy/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ind/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-is/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-it/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-iw/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ja/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-jv/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ka/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-kk/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-km/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-kn/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ko/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ku/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ky/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-lt/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-lv/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-mk/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ml/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-mn/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-mr/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ms/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-my/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-nl/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-nn/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-no/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-or/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-pa/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-pl/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-pt-rPT/01-core.xml | 4 ++-- AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml | 9 ++++----- AnkiDroid/src/main/res/values-pt-rPT/04-network.xml | 2 +- AnkiDroid/src/main/res/values-ro/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ru/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-sat/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-sc/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-sk/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-sl/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-sq/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-sr/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ss/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-sv/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-sw/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ta/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-te/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-tg/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-tgl/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-th/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ti/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-tn/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-tr/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ts/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-tt/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-uk/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ur/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-uz/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-ve/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-vi/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-wo/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-xh/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-yue/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml | 1 - AnkiDroid/src/main/res/values-zu/03-dialogs.xml | 1 - 98 files changed, 13 insertions(+), 106 deletions(-) diff --git a/AnkiDroid/src/main/res/values-af/03-dialogs.xml b/AnkiDroid/src/main/res/values-af/03-dialogs.xml index b2b824e68d75..d5bce816b0e6 100644 --- a/AnkiDroid/src/main/res/values-af/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-af/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-am/03-dialogs.xml b/AnkiDroid/src/main/res/values-am/03-dialogs.xml index b7b524ed69cc..2d06df7413c3 100644 --- a/AnkiDroid/src/main/res/values-am/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-am/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ar/01-core.xml b/AnkiDroid/src/main/res/values-ar/01-core.xml index 9bed997008dc..e8976db7f8f3 100644 --- a/AnkiDroid/src/main/res/values-ar/01-core.xml +++ b/AnkiDroid/src/main/res/values-ar/01-core.xml @@ -272,5 +272,5 @@ صورة معماة حذف الحساب - Instant card + بطاقة فورية diff --git a/AnkiDroid/src/main/res/values-ar/03-dialogs.xml b/AnkiDroid/src/main/res/values-ar/03-dialogs.xml index 2909d1ad45b4..0a800c6b71a6 100644 --- a/AnkiDroid/src/main/res/values-ar/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ar/03-dialogs.xml @@ -288,7 +288,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-az/03-dialogs.xml b/AnkiDroid/src/main/res/values-az/03-dialogs.xml index 29e60ae44978..205d8b402cf8 100644 --- a/AnkiDroid/src/main/res/values-az/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-az/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-be/03-dialogs.xml b/AnkiDroid/src/main/res/values-be/03-dialogs.xml index cfdf690b39b4..9c712987d760 100644 --- a/AnkiDroid/src/main/res/values-be/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-be/03-dialogs.xml @@ -274,7 +274,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-bg/03-dialogs.xml b/AnkiDroid/src/main/res/values-bg/03-dialogs.xml index 4e361763e31e..ed2ca2fde57e 100644 --- a/AnkiDroid/src/main/res/values-bg/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-bg/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-bn/03-dialogs.xml b/AnkiDroid/src/main/res/values-bn/03-dialogs.xml index 7b3449e9f842..2decffbab229 100644 --- a/AnkiDroid/src/main/res/values-bn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-bn/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ca/03-dialogs.xml b/AnkiDroid/src/main/res/values-ca/03-dialogs.xml index 57a2d7ea4e0f..b4bf13137ec2 100644 --- a/AnkiDroid/src/main/res/values-ca/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ca/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml b/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml index ae93ce460ae6..80664e9ae6c7 100644 --- a/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-cs/03-dialogs.xml b/AnkiDroid/src/main/res/values-cs/03-dialogs.xml index f2c94a3c8a7b..42d7ba177171 100644 --- a/AnkiDroid/src/main/res/values-cs/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-cs/03-dialogs.xml @@ -272,7 +272,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze - The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + Systémový WebView je zastaralý. Některé funkce nebudou fungovat správně. Aktualizujte jej prosím.\n\nNainstalovaná verze: %1$d\nMinimální požadovaná verze: %2$d diff --git a/AnkiDroid/src/main/res/values-cs/04-network.xml b/AnkiDroid/src/main/res/values-cs/04-network.xml index 97700bd8ecbb..44de4afb01e9 100644 --- a/AnkiDroid/src/main/res/values-cs/04-network.xml +++ b/AnkiDroid/src/main/res/values-cs/04-network.xml @@ -70,7 +70,7 @@ Synchronizace Úplná synchronizace z místního úložiště Kolekce synchronizována - Collection synced. Media is being synced in the background. + Kolekce synchronizována. Multimédia se synchronizují na pozadí. Databáze je poškozena. Prosím opravte jí předtím, než se ji znovu pokusíte synchronizovat.\n\nViz %s, kde jsou informace o opravě databáze. Místní diff --git a/AnkiDroid/src/main/res/values-da/03-dialogs.xml b/AnkiDroid/src/main/res/values-da/03-dialogs.xml index b2d74ef8f07a..3180bc04145c 100644 --- a/AnkiDroid/src/main/res/values-da/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-da/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-de/03-dialogs.xml b/AnkiDroid/src/main/res/values-de/03-dialogs.xml index c67aa0a1479e..04f813689248 100644 --- a/AnkiDroid/src/main/res/values-de/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-de/03-dialogs.xml @@ -254,7 +254,6 @@ Cloze-Notiztyp erforderlich Kein Cloze-Notiztyp gefunden. Öffnen Sie den Notiz-Editor oder versuchen Sie es erneut, nachdem Sie einen Cloze-Notiztyp hinzugefügt haben. Offen - Single tap text to cloze Das System-WebView ist veraltet. Einige Funktionen werden nicht korrekt funktionieren. Bitte aktualisieren Sie es.\n\nInstallierte Version: %1$d\nMindestanforderung: %2$d diff --git a/AnkiDroid/src/main/res/values-el/03-dialogs.xml b/AnkiDroid/src/main/res/values-el/03-dialogs.xml index 95ef4dc72901..0417f5c2b24c 100644 --- a/AnkiDroid/src/main/res/values-el/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-el/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-eo/03-dialogs.xml b/AnkiDroid/src/main/res/values-eo/03-dialogs.xml index 7f7693084fa8..cc0419129514 100644 --- a/AnkiDroid/src/main/res/values-eo/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-eo/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Malfermi - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml b/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml index 3dfda498bd59..7127603dd726 100644 --- a/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml b/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml index 013d8c572c41..233e77890d32 100644 --- a/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-et/03-dialogs.xml b/AnkiDroid/src/main/res/values-et/03-dialogs.xml index d5441fb90f66..ba25be3e26e8 100644 --- a/AnkiDroid/src/main/res/values-et/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-et/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-eu/03-dialogs.xml b/AnkiDroid/src/main/res/values-eu/03-dialogs.xml index 4074bacad3ba..e48ce0051554 100644 --- a/AnkiDroid/src/main/res/values-eu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-eu/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-fa/03-dialogs.xml b/AnkiDroid/src/main/res/values-fa/03-dialogs.xml index 7eca01b2ef8e..ed55abacb864 100644 --- a/AnkiDroid/src/main/res/values-fa/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fa/03-dialogs.xml @@ -254,7 +254,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-fi/03-dialogs.xml b/AnkiDroid/src/main/res/values-fi/03-dialogs.xml index d813e718bf40..c5d91ad7cd37 100644 --- a/AnkiDroid/src/main/res/values-fi/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fi/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-fil/03-dialogs.xml b/AnkiDroid/src/main/res/values-fil/03-dialogs.xml index 2b9c12267f39..43db4504ecf0 100644 --- a/AnkiDroid/src/main/res/values-fil/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fil/03-dialogs.xml @@ -257,7 +257,6 @@ Mga file na may di-wastong pag-encode:%d Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-fr/03-dialogs.xml b/AnkiDroid/src/main/res/values-fr/03-dialogs.xml index 163a1d9b7dea..d4aa8c68cfe5 100644 --- a/AnkiDroid/src/main/res/values-fr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fr/03-dialogs.xml @@ -254,7 +254,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-fy/03-dialogs.xml b/AnkiDroid/src/main/res/values-fy/03-dialogs.xml index 7b9003a709ec..938497444a06 100644 --- a/AnkiDroid/src/main/res/values-fy/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fy/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ga/03-dialogs.xml b/AnkiDroid/src/main/res/values-ga/03-dialogs.xml index f7ea069f7c5f..11a0314a4b7b 100644 --- a/AnkiDroid/src/main/res/values-ga/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ga/03-dialogs.xml @@ -280,7 +280,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-gl/03-dialogs.xml b/AnkiDroid/src/main/res/values-gl/03-dialogs.xml index e455865fbdaf..4ddaa7e154ac 100644 --- a/AnkiDroid/src/main/res/values-gl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-gl/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-got/03-dialogs.xml b/AnkiDroid/src/main/res/values-got/03-dialogs.xml index 477b4b0b96a7..f51b3a593f66 100644 --- a/AnkiDroid/src/main/res/values-got/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-got/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-gu/03-dialogs.xml b/AnkiDroid/src/main/res/values-gu/03-dialogs.xml index 7021323e03b4..6548f5e0ba9a 100644 --- a/AnkiDroid/src/main/res/values-gu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-gu/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-gu/04-network.xml b/AnkiDroid/src/main/res/values-gu/04-network.xml index 033573cfc12b..b1a700c0b19e 100644 --- a/AnkiDroid/src/main/res/values-gu/04-network.xml +++ b/AnkiDroid/src/main/res/values-gu/04-network.xml @@ -45,9 +45,9 @@ --> - You are offline - Sync error - Error + તમે ઑફલાઇન છો + સમન્વયન ભૂલ + ભૂલ Retry Get shared decks A network error has occurred diff --git a/AnkiDroid/src/main/res/values-heb/03-dialogs.xml b/AnkiDroid/src/main/res/values-heb/03-dialogs.xml index a58de0ec07df..c58e9db8c984 100644 --- a/AnkiDroid/src/main/res/values-heb/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-heb/03-dialogs.xml @@ -271,7 +271,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-hi/03-dialogs.xml b/AnkiDroid/src/main/res/values-hi/03-dialogs.xml index a81c38c4a680..8700986266b3 100644 --- a/AnkiDroid/src/main/res/values-hi/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hi/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-hr/03-dialogs.xml b/AnkiDroid/src/main/res/values-hr/03-dialogs.xml index f26f1b222fed..9472f65feb64 100644 --- a/AnkiDroid/src/main/res/values-hr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hr/03-dialogs.xml @@ -264,7 +264,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-hu/03-dialogs.xml b/AnkiDroid/src/main/res/values-hu/03-dialogs.xml index 8a377347a78b..caf4f1fcf52c 100644 --- a/AnkiDroid/src/main/res/values-hu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hu/03-dialogs.xml @@ -254,7 +254,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-hy/03-dialogs.xml b/AnkiDroid/src/main/res/values-hy/03-dialogs.xml index 63e27d1e396c..3b5f4ff6369a 100644 --- a/AnkiDroid/src/main/res/values-hy/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hy/03-dialogs.xml @@ -254,7 +254,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ind/03-dialogs.xml b/AnkiDroid/src/main/res/values-ind/03-dialogs.xml index 7aca85bfb3d9..fb15d6525215 100644 --- a/AnkiDroid/src/main/res/values-ind/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ind/03-dialogs.xml @@ -248,7 +248,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-is/03-dialogs.xml b/AnkiDroid/src/main/res/values-is/03-dialogs.xml index e98e2bdeae85..13b381bf73d2 100644 --- a/AnkiDroid/src/main/res/values-is/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-is/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-it/03-dialogs.xml b/AnkiDroid/src/main/res/values-it/03-dialogs.xml index 8bb619339b2c..ffd104fb259b 100644 --- a/AnkiDroid/src/main/res/values-it/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-it/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-iw/03-dialogs.xml b/AnkiDroid/src/main/res/values-iw/03-dialogs.xml index a58de0ec07df..c58e9db8c984 100644 --- a/AnkiDroid/src/main/res/values-iw/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-iw/03-dialogs.xml @@ -271,7 +271,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml index fa7816cdcb8b..091e34422252 100644 --- a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml @@ -247,7 +247,6 @@ 「穴埋め問題」用のノートタイプが必要です 「穴埋め問題」に対応したノートタイプが見つかりませんでした。アプリで「穴埋め問題」に対応したノートタイプを追加してからもう一度試すか、それ以外のノートタイプのノートを編集するため、「開く」ボタンを押してください。 開く - シングルタップで穴埋め問題 「AndroidシステムのWebView 」(または「Android System WebView」)が古くなっています。いくつかの機能が正しく動作しません。更新してください。\n\nインストールされているバージョン: %1$d\n最低限必要なバージョン: %2$d diff --git a/AnkiDroid/src/main/res/values-jv/03-dialogs.xml b/AnkiDroid/src/main/res/values-jv/03-dialogs.xml index b67423cd4fa6..f1f35c733f05 100644 --- a/AnkiDroid/src/main/res/values-jv/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-jv/03-dialogs.xml @@ -248,7 +248,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ka/03-dialogs.xml b/AnkiDroid/src/main/res/values-ka/03-dialogs.xml index aab7460fd2e8..44c11864667c 100644 --- a/AnkiDroid/src/main/res/values-ka/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ka/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-kk/03-dialogs.xml b/AnkiDroid/src/main/res/values-kk/03-dialogs.xml index a146fb51e384..28ab9ec10660 100644 --- a/AnkiDroid/src/main/res/values-kk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-kk/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-km/03-dialogs.xml b/AnkiDroid/src/main/res/values-km/03-dialogs.xml index a599d07f7667..110351f03a39 100644 --- a/AnkiDroid/src/main/res/values-km/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-km/03-dialogs.xml @@ -248,7 +248,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-kn/03-dialogs.xml b/AnkiDroid/src/main/res/values-kn/03-dialogs.xml index f1620ae643b6..fef2942cbeb0 100644 --- a/AnkiDroid/src/main/res/values-kn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-kn/03-dialogs.xml @@ -254,7 +254,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ko/03-dialogs.xml b/AnkiDroid/src/main/res/values-ko/03-dialogs.xml index efd95ed93998..c6897836dff6 100644 --- a/AnkiDroid/src/main/res/values-ko/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ko/03-dialogs.xml @@ -248,7 +248,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ku/03-dialogs.xml b/AnkiDroid/src/main/res/values-ku/03-dialogs.xml index ae93ce460ae6..80664e9ae6c7 100644 --- a/AnkiDroid/src/main/res/values-ku/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ku/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ky/03-dialogs.xml b/AnkiDroid/src/main/res/values-ky/03-dialogs.xml index a1a4978394b3..43bdad1b692f 100644 --- a/AnkiDroid/src/main/res/values-ky/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ky/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-lt/03-dialogs.xml b/AnkiDroid/src/main/res/values-lt/03-dialogs.xml index 86e01efccd16..3da29e029914 100644 --- a/AnkiDroid/src/main/res/values-lt/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-lt/03-dialogs.xml @@ -272,7 +272,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-lv/03-dialogs.xml b/AnkiDroid/src/main/res/values-lv/03-dialogs.xml index 761d90e9a6c5..c6f06f46a2d2 100644 --- a/AnkiDroid/src/main/res/values-lv/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-lv/03-dialogs.xml @@ -264,7 +264,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-mk/03-dialogs.xml b/AnkiDroid/src/main/res/values-mk/03-dialogs.xml index 0737e2085473..07c201640b45 100644 --- a/AnkiDroid/src/main/res/values-mk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mk/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ml/03-dialogs.xml b/AnkiDroid/src/main/res/values-ml/03-dialogs.xml index aaebaa5c4e8c..5ae1f2af79b5 100644 --- a/AnkiDroid/src/main/res/values-ml/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ml/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-mn/03-dialogs.xml b/AnkiDroid/src/main/res/values-mn/03-dialogs.xml index 11c31e36bb0b..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-mn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mn/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-mr/03-dialogs.xml b/AnkiDroid/src/main/res/values-mr/03-dialogs.xml index e3bf35d3b266..8c670a6f630f 100644 --- a/AnkiDroid/src/main/res/values-mr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mr/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ms/03-dialogs.xml b/AnkiDroid/src/main/res/values-ms/03-dialogs.xml index 824b9ca8795d..d77fdd6042da 100644 --- a/AnkiDroid/src/main/res/values-ms/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ms/03-dialogs.xml @@ -248,7 +248,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-my/03-dialogs.xml b/AnkiDroid/src/main/res/values-my/03-dialogs.xml index 8585bbf3b647..15b91c530f36 100644 --- a/AnkiDroid/src/main/res/values-my/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-my/03-dialogs.xml @@ -248,7 +248,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-nl/03-dialogs.xml b/AnkiDroid/src/main/res/values-nl/03-dialogs.xml index da8390328d46..e5aa19200793 100644 --- a/AnkiDroid/src/main/res/values-nl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-nl/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-nn/03-dialogs.xml b/AnkiDroid/src/main/res/values-nn/03-dialogs.xml index 33d0dfeebeb2..fdf1e3021453 100644 --- a/AnkiDroid/src/main/res/values-nn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-nn/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-no/03-dialogs.xml b/AnkiDroid/src/main/res/values-no/03-dialogs.xml index d25e908f6f6d..d4070917c157 100644 --- a/AnkiDroid/src/main/res/values-no/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-no/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-or/03-dialogs.xml b/AnkiDroid/src/main/res/values-or/03-dialogs.xml index 2bfda8a18a7a..e36a3156a075 100644 --- a/AnkiDroid/src/main/res/values-or/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-or/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-pa/03-dialogs.xml b/AnkiDroid/src/main/res/values-pa/03-dialogs.xml index 79fb9f7b89f1..4843cb22d221 100644 --- a/AnkiDroid/src/main/res/values-pa/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pa/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-pl/03-dialogs.xml b/AnkiDroid/src/main/res/values-pl/03-dialogs.xml index f3a24c33f117..fe8da3065b8e 100644 --- a/AnkiDroid/src/main/res/values-pl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pl/03-dialogs.xml @@ -272,7 +272,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml b/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml index 9a04574fbc6f..a9f22a956ea4 100644 --- a/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml b/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml index 1702aaaa3faf..de6ee149e54c 100644 --- a/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml +++ b/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml @@ -131,7 +131,7 @@ Pesquisar baralhos Nome de baralho inválido Parabéns! Terminou por agora. - Deck finished for now! %s + Baralho finalizado por enquanto! %s Nenhuma ficha por rever Armazenamento do dispositivo não montado Sincronizar @@ -248,5 +248,5 @@ Oclusão de imagem Eliminar conta - Instant card + Cartão instantâneo diff --git a/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml b/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml index e6a6fc3795da..9a4bc5c39ac6 100644 --- a/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml @@ -253,10 +253,9 @@ Desde Até - Cloze Type Note Required - No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. - Open - Single tap text to cloze + Nota de tipo Virável Necessária + Nenhuma nota de tipo Virável encontrada, abra o Editor de Notas ou tente novamente após adicionar uma nota de tipo Virável. + Abrir - The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + O sistema WebView está desatualizado. Alguns recursos não funcionarão corretamente. Atualize-o.\n\nVersão instalada: %1$d\nVersão mínima necessária: %2$d diff --git a/AnkiDroid/src/main/res/values-pt-rPT/04-network.xml b/AnkiDroid/src/main/res/values-pt-rPT/04-network.xml index bb2dba48ff21..1e13998f31c1 100644 --- a/AnkiDroid/src/main/res/values-pt-rPT/04-network.xml +++ b/AnkiDroid/src/main/res/values-pt-rPT/04-network.xml @@ -70,7 +70,7 @@ Sincronização Sincronização completa a partir dos dados locais Coleção sincronizada - Collection synced. Media is being synced in the background. + Coleção sincronizada. As mídias estão sendo sincronizadas em segundo plano. A sua base de dados está corrompida. Por favor corrija-a antes de tentar novamente uma sincronização.\n\nVeja %s para obter informações sobre como reparar a base de dados. Local diff --git a/AnkiDroid/src/main/res/values-ro/03-dialogs.xml b/AnkiDroid/src/main/res/values-ro/03-dialogs.xml index e2f8090e62bd..1012cb1082ea 100644 --- a/AnkiDroid/src/main/res/values-ro/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ro/03-dialogs.xml @@ -264,7 +264,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ru/03-dialogs.xml b/AnkiDroid/src/main/res/values-ru/03-dialogs.xml index b2f9e16a9f7a..6f321ba1ccae 100644 --- a/AnkiDroid/src/main/res/values-ru/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ru/03-dialogs.xml @@ -273,7 +273,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sat/03-dialogs.xml b/AnkiDroid/src/main/res/values-sat/03-dialogs.xml index e9a005177c1c..c835d8064214 100644 --- a/AnkiDroid/src/main/res/values-sat/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sat/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sc/03-dialogs.xml b/AnkiDroid/src/main/res/values-sc/03-dialogs.xml index 168123039be0..2134871aa271 100644 --- a/AnkiDroid/src/main/res/values-sc/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sc/03-dialogs.xml @@ -270,7 +270,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sk/03-dialogs.xml b/AnkiDroid/src/main/res/values-sk/03-dialogs.xml index 64ea6276ea3e..bff167a01072 100644 --- a/AnkiDroid/src/main/res/values-sk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sk/03-dialogs.xml @@ -270,7 +270,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sl/03-dialogs.xml b/AnkiDroid/src/main/res/values-sl/03-dialogs.xml index adbd63bd111e..2cf9c93e032a 100644 --- a/AnkiDroid/src/main/res/values-sl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sl/03-dialogs.xml @@ -272,7 +272,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sq/03-dialogs.xml b/AnkiDroid/src/main/res/values-sq/03-dialogs.xml index f90ce97a5d58..46782b2ea83a 100644 --- a/AnkiDroid/src/main/res/values-sq/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sq/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sr/03-dialogs.xml b/AnkiDroid/src/main/res/values-sr/03-dialogs.xml index bdbdd5f705e6..9917e1e6ce91 100644 --- a/AnkiDroid/src/main/res/values-sr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sr/03-dialogs.xml @@ -264,7 +264,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ss/03-dialogs.xml b/AnkiDroid/src/main/res/values-ss/03-dialogs.xml index 11c31e36bb0b..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-ss/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ss/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sv/03-dialogs.xml b/AnkiDroid/src/main/res/values-sv/03-dialogs.xml index c2d81f146261..0c576931e50e 100644 --- a/AnkiDroid/src/main/res/values-sv/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sv/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-sw/03-dialogs.xml b/AnkiDroid/src/main/res/values-sw/03-dialogs.xml index 11c31e36bb0b..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-sw/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sw/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ta/03-dialogs.xml b/AnkiDroid/src/main/res/values-ta/03-dialogs.xml index 7bdfb31c044f..bda43a1ce1d4 100644 --- a/AnkiDroid/src/main/res/values-ta/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ta/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-te/03-dialogs.xml b/AnkiDroid/src/main/res/values-te/03-dialogs.xml index 33e7e2680449..a0dbe1bfd02c 100644 --- a/AnkiDroid/src/main/res/values-te/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-te/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-tg/03-dialogs.xml b/AnkiDroid/src/main/res/values-tg/03-dialogs.xml index 165c214a1f39..2b091d79c9e2 100644 --- a/AnkiDroid/src/main/res/values-tg/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tg/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml b/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml index 98ccdc9ad4e4..72a0b3cf8769 100644 --- a/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-th/03-dialogs.xml b/AnkiDroid/src/main/res/values-th/03-dialogs.xml index b67423cd4fa6..f1f35c733f05 100644 --- a/AnkiDroid/src/main/res/values-th/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-th/03-dialogs.xml @@ -248,7 +248,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ti/03-dialogs.xml b/AnkiDroid/src/main/res/values-ti/03-dialogs.xml index 11c31e36bb0b..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-ti/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ti/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-tn/03-dialogs.xml b/AnkiDroid/src/main/res/values-tn/03-dialogs.xml index 11c31e36bb0b..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-tn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tn/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-tr/03-dialogs.xml b/AnkiDroid/src/main/res/values-tr/03-dialogs.xml index 613e07fced42..ffb89753b71c 100644 --- a/AnkiDroid/src/main/res/values-tr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tr/03-dialogs.xml @@ -256,7 +256,6 @@ Boşluklu Türden Not Gerekiyor Boşluklu türden not bulunmuyor, Not Düzenleyiciyi açın ya da Boşluklu türden bir not ekledikten sonra yeniden deneyin. - Boşluk bırakmak için metne bir kez dokunun Sistem WebView\'su güncel değil. Bazı özellikler doğru çalışmayacak. Lütfen güncelleyin.\n\nYüklü sürüm: %1$d\nGereken en düşük sürüm: %2$d diff --git a/AnkiDroid/src/main/res/values-ts/03-dialogs.xml b/AnkiDroid/src/main/res/values-ts/03-dialogs.xml index 11c31e36bb0b..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-ts/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ts/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-tt/03-dialogs.xml b/AnkiDroid/src/main/res/values-tt/03-dialogs.xml index bae272ca001d..eb3823171c0b 100644 --- a/AnkiDroid/src/main/res/values-tt/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tt/03-dialogs.xml @@ -248,7 +248,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-uk/03-dialogs.xml b/AnkiDroid/src/main/res/values-uk/03-dialogs.xml index ddc8f9f5c8af..9b88fab45539 100644 --- a/AnkiDroid/src/main/res/values-uk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-uk/03-dialogs.xml @@ -272,7 +272,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ur/03-dialogs.xml b/AnkiDroid/src/main/res/values-ur/03-dialogs.xml index 45f812782612..48f4b6af0e5e 100644 --- a/AnkiDroid/src/main/res/values-ur/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ur/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-uz/03-dialogs.xml b/AnkiDroid/src/main/res/values-uz/03-dialogs.xml index d574ef8319ca..73ff762ae652 100644 --- a/AnkiDroid/src/main/res/values-uz/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-uz/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-ve/03-dialogs.xml b/AnkiDroid/src/main/res/values-ve/03-dialogs.xml index 11c31e36bb0b..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-ve/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ve/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-vi/03-dialogs.xml b/AnkiDroid/src/main/res/values-vi/03-dialogs.xml index 4190673db9fb..0414affcf26f 100644 --- a/AnkiDroid/src/main/res/values-vi/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-vi/03-dialogs.xml @@ -248,7 +248,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-wo/03-dialogs.xml b/AnkiDroid/src/main/res/values-wo/03-dialogs.xml index b67423cd4fa6..f1f35c733f05 100644 --- a/AnkiDroid/src/main/res/values-wo/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-wo/03-dialogs.xml @@ -248,7 +248,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-xh/03-dialogs.xml b/AnkiDroid/src/main/res/values-xh/03-dialogs.xml index 11c31e36bb0b..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-xh/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-xh/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-yue/03-dialogs.xml b/AnkiDroid/src/main/res/values-yue/03-dialogs.xml index 49d3a7439611..c0d122875325 100644 --- a/AnkiDroid/src/main/res/values-yue/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-yue/03-dialogs.xml @@ -248,7 +248,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml index add3abff547e..a1042c33b8bd 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml @@ -248,7 +248,6 @@ 需要Cloze类型笔记 未找到Cloze类型笔记,打开笔记编辑器或添加Cloze类型笔记后重试。 打开 - 要关闭,请轻按一次文本 系统 WebView 已过时。有些功能将无法正常工作。请更新它。\n\n已安装版本: %1$d\n所需最低版本: %2$d diff --git a/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml b/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml index 2201ecd54893..3541677286a3 100644 --- a/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml @@ -248,7 +248,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d diff --git a/AnkiDroid/src/main/res/values-zu/03-dialogs.xml b/AnkiDroid/src/main/res/values-zu/03-dialogs.xml index 11c31e36bb0b..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-zu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zu/03-dialogs.xml @@ -256,7 +256,6 @@ Cloze Type Note Required No Cloze type note found, open the Note Editor or try again after adding a Cloze type note. Open - Single tap text to cloze The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d From 0858f2cf6bd0a8112cac4440b45713ab56601e02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Naz=C3=A1rio?= Date: Sun, 2 Jun 2024 01:29:40 +0100 Subject: [PATCH 082/138] Fix #15553: Start of Next Day Not Working Start of Next Day wasn't working when changing to the past Fixed by using setPreferences instead of config.set --- .../com/ichi2/anki/preferences/Preferences.kt | 16 ++++++++++++---- .../ichi2/anki/preferences/PreferencesTest.kt | 13 ++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/preferences/Preferences.kt b/AnkiDroid/src/main/java/com/ichi2/anki/preferences/Preferences.kt index fa996d910d84..61a98ac8a706 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/preferences/Preferences.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/preferences/Preferences.kt @@ -32,6 +32,7 @@ import androidx.fragment.app.FragmentContainerView import androidx.fragment.app.commit import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat +import anki.config.copy import com.bytehamster.lib.preferencesearch.SearchPreferenceResult import com.bytehamster.lib.preferencesearch.SearchPreferenceResultListener import com.google.android.material.appbar.AppBarLayout @@ -43,6 +44,8 @@ import com.ichi2.anki.DeckPicker import com.ichi2.anki.R import com.ichi2.anki.launchCatchingTask import com.ichi2.anki.services.BootService.Companion.scheduleNotification +import com.ichi2.annotations.NeedsTest +import com.ichi2.libanki.undoableOp import com.ichi2.libanki.utils.TimeManager import com.ichi2.themes.setTransparentStatusBar import com.ichi2.utils.getInstanceFromClassName @@ -229,15 +232,20 @@ class Preferences : /** Sets the hour that the collection rolls over to the next day */ @VisibleForTesting + @NeedsTest("ensure Start of Next Day is handled by the scheduler") suspend fun setDayOffset(context: Context, hours: Int) { - withCol { - config.set("rollover", hours) - scheduleNotification(TimeManager.time, context) + val prefs = withCol { getPreferences() } + val newPrefs = prefs.copy { scheduling = prefs.scheduling.copy { rollover = hours } } + + undoableOp { + setPreferences(newPrefs) } + scheduleNotification(TimeManager.time, context) Timber.i("set day offset: '%d'", hours) } + suspend fun getDayOffset(): Int { - return withCol { config.get("rollover") ?: 4 } + return withCol { getPreferences().scheduling.rollover } } } } diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/preferences/PreferencesTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/preferences/PreferencesTest.kt index 4a682a39a9f4..6d758ee80644 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/preferences/PreferencesTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/preferences/PreferencesTest.kt @@ -27,7 +27,6 @@ import com.ichi2.anki.preferences.Preferences.Companion.setDayOffset import com.ichi2.libanki.exception.ConfirmModSchemaException import com.ichi2.preferences.HeaderPreference import com.ichi2.testutils.getJavaMethodAsAccessible -import kotlinx.coroutines.runBlocking import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.equalTo import org.junit.Before @@ -53,7 +52,7 @@ class PreferencesTest : RobolectricTest() { @Test fun testDayOffsetExhaustive() { - runBlocking { + runTest { for (i in 0..23) { setDayOffset(preferences, i) assertThat(getDayOffset(), equalTo(i)) @@ -64,7 +63,7 @@ class PreferencesTest : RobolectricTest() { @Test @Throws(ConfirmModSchemaException::class) fun testDayOffsetExhaustiveV2() { - runBlocking { + runTest { for (i in 0..23) { setDayOffset(preferences, i) assertThat(getDayOffset(), equalTo(i)) @@ -95,9 +94,9 @@ class PreferencesTest : RobolectricTest() { @Test @Throws(ConfirmModSchemaException::class) fun setDayOffsetSetsConfig() { - val offset = runBlocking { getDayOffset() } - assertThat("Default offset should be 4", offset, equalTo(4)) - runBlocking { setDayOffset(preferences, 2) } - assertThat("rollover config should be set to new value", col.config.get("rollover") ?: 4, equalTo(2)) + runTest { + setDayOffset(preferences, 2) + assertThat("rollover config should be set to new value", col.config.get("rollover") ?: 4, equalTo(2)) + } } } From 39fda2f9771d40653f0c409a2d2aa7fb2e1770b2 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Mon, 17 Jun 2024 07:58:11 -0500 Subject: [PATCH 083/138] Dependency updates 20240617 (#16609) * Update Gradle Wrapper from 8.7 to 8.8. Signed-off-by: gradle-update-robot * chore(deps): bump com.google.protobuf:protobuf-kotlin-lite Bumps com.google.protobuf:protobuf-kotlin-lite from 4.27.0 to 4.27.1. --- updated-dependencies: - dependency-name: com.google.protobuf:protobuf-kotlin-lite dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore(deps): bump org.jetbrains.kotlinx:kotlinx-serialization-json Bumps [org.jetbrains.kotlinx:kotlinx-serialization-json](https://github.com/Kotlin/kotlinx.serialization) from 1.6.3 to 1.7.0. - [Release notes](https://github.com/Kotlin/kotlinx.serialization/releases) - [Changelog](https://github.com/Kotlin/kotlinx.serialization/blob/master/CHANGELOG.md) - [Commits](https://github.com/Kotlin/kotlinx.serialization/compare/v1.6.3...v1.7.0) --- updated-dependencies: - dependency-name: org.jetbrains.kotlinx:kotlinx-serialization-json dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * build(deps): bump androidxFragmentKtx from 1.7.1 to 1.8.0 Bumps `androidxFragmentKtx` from 1.7.1 to 1.8.0. Updates `androidx.fragment:fragment-ktx` from 1.7.1 to 1.8.0 Updates `androidx.fragment:fragment-testing` from 1.7.1 to 1.8.0 Updates `androidx.fragment:fragment-testing-manifest` from 1.7.1 to 1.8.0 --- updated-dependencies: - dependency-name: androidx.fragment:fragment-ktx dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: androidx.fragment:fragment-testing dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: androidx.fragment:fragment-testing-manifest dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * build(deps): bump androidGradlePlugin from 8.4.1 to 8.5.0 Bumps `androidGradlePlugin` from 8.4.1 to 8.5.0. Updates `com.android.application` from 8.4.1 to 8.5.0 Updates `com.android.library` from 8.4.1 to 8.5.0 --- updated-dependencies: - dependency-name: com.android.application dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.android.library dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * build(deps): bump lint from 31.4.1 to 31.5.0 Bumps `lint` from 31.4.1 to 31.5.0. Updates `com.android.tools.lint:lint-api` from 31.4.1 to 31.5.0 Updates `com.android.tools.lint:lint` from 31.4.1 to 31.5.0 Updates `com.android.tools.lint:lint-tests` from 31.4.1 to 31.5.0 --- updated-dependencies: - dependency-name: com.android.tools.lint:lint-api dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.android.tools.lint:lint dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.android.tools.lint:lint-tests dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * build(deps): bump com.github.triplet.play from 3.9.1 to 3.10.0 Bumps com.github.triplet.play from 3.9.1 to 3.10.0. --- updated-dependencies: - dependency-name: com.github.triplet.play dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --------- Signed-off-by: gradle-update-robot Signed-off-by: dependabot[bot] Co-authored-by: gradle-update-robot Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 12 ++++++------ gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 20eadb840748..b4ca516900b9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ minSdk = "23" # also in testlib/build.gradle.kts targetSdk = "33" # also in ../robolectricDownloader.gradle acra = '5.11.3' amazonappstorepublisher = "0.1.0" -androidGradlePlugin = "8.4.1" +androidGradlePlugin = "8.5.0" androidxActivity = "1.9.0" androidxAnnotation = "1.8.0" androidxAppCompat = "1.7.0" @@ -12,7 +12,7 @@ androidxBrowser = "1.8.0" androidxConstraintlayout = "2.1.4" androidxCoreKtx = "1.13.1" androidxExifinterface = "1.3.7" -androidxFragmentKtx = "1.7.1" +androidxFragmentKtx = "1.8.0" androidxImageCropper = "4.5.0" androidxMedia = "1.7.0" androidxPreferenceKtx = "1.2.1" @@ -51,10 +51,10 @@ junitVintageEngine = "5.10.2" kotlin = '2.0.0' kotlinReflect = "2.0.0" kotlinTest = "2.0.0" -kotlinxSerializationJson = "1.6.3" +kotlinxSerializationJson = "1.7.0" ktlint = "11.6.1" leakcanaryAndroid = "2.14" -lint = '31.4.1' +lint = '31.5.0' material = "1.12.0" materialTapTargetPrompt = "3.3.2" mockitoInline = "5.2.0" @@ -62,14 +62,14 @@ mockitoKotlin = "5.3.1" mockk = "1.13.11" nanohttpd = "2.3.1" okhttp = "4.12.0" -protobufKotlinLite = "4.27.0" +protobufKotlinLite = "4.27.1" robolectric = "4.12.2" searchpreference = "2.5.1" seismic = "1.0.3" sharedPreferencesMock = "1.2.4" slf4jTimber = "3.1" timber = "5.0.1" -triplet = "3.9.1" +triplet = "3.10.0" turbine = "1.1.0" workRuntimeKtx = "2.9.0" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23a4f05..a4413138c96c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a426907..b740cf13397a 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. From bb6bb032e16f5428770c1967652ba0d506f40c9f Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Mon, 17 Jun 2024 07:34:16 -0500 Subject: [PATCH 084/138] build(deps): have dependabot ignore anki-android-backend dep It resumed proposing PRs for this dependency after moving to the version catalog style of version specification in gradle, which has been confusing me. I believe it is because the name now needs to be the version catalog alias name, not the maven repository coordinates, with my hunch based on the naming of the PRs now being an update for `ankiBackend` vs the coordinates first --- .github/dependabot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 88efb6afb7e1..ea3783cd90ac 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -15,7 +15,7 @@ updates: - "dependencies" ignore: # Ignore all Rust backend updates, these are always done as manual pulls - - dependency-name: io.github.david-allison:anki-android-backend + - dependency-name: ankiBackend - package-ecosystem: npm directory: "/tools/localization" schedule: From 4e161d1d5236f9c81efbb566b65f53e5d6696204 Mon Sep 17 00:00:00 2001 From: AnkiDroid Translations Date: Mon, 17 Jun 2024 16:25:52 +0000 Subject: [PATCH 085/138] Updated strings from Crowdin --- AnkiDroid/src/main/res/values-cs/01-core.xml | 2 +- .../src/main/res/values-cs/02-strings.xml | 8 +- AnkiDroid/src/main/res/values-de/01-core.xml | 2 +- .../src/main/res/values-de/04-network.xml | 2 +- .../src/main/res/values-gu/04-network.xml | 44 ++--- .../src/main/res/values-gu/07-cardbrowser.xml | 84 ++++----- .../src/main/res/values-gu/10-preferences.xml | 168 +++++++++--------- .../src/main/res/values-gu/11-arrays.xml | 52 +++--- .../res/values-gu/16-multimedia-editor.xml | 58 +++--- .../src/main/res/values-ja/03-dialogs.xml | 2 +- .../src/main/res/values-ja/10-preferences.xml | 2 +- .../src/main/res/values-mr/02-strings.xml | 4 +- .../src/main/res/values-mr/03-dialogs.xml | 32 ++-- .../src/main/res/values-mr/10-preferences.xml | 98 +++++----- .../src/main/res/values-mr/11-arrays.xml | 16 +- .../res/values-mr/16-multimedia-editor.xml | 10 +- 16 files changed, 292 insertions(+), 292 deletions(-) diff --git a/AnkiDroid/src/main/res/values-cs/01-core.xml b/AnkiDroid/src/main/res/values-cs/01-core.xml index 850b8b4a6527..93a6ca42a016 100644 --- a/AnkiDroid/src/main/res/values-cs/01-core.xml +++ b/AnkiDroid/src/main/res/values-cs/01-core.xml @@ -137,7 +137,7 @@ Hledat balíček Neplatný název balíčku Blahopřejeme! Prozatím máte hotovo. - Deck finished for now! %s + Balíček byl prozatím dokončen! %s Žádné karty ještě nejsou ke zkoušení Zařízení úložiště není připojeno Synchronizovat diff --git a/AnkiDroid/src/main/res/values-cs/02-strings.xml b/AnkiDroid/src/main/res/values-cs/02-strings.xml index 43bd3ad8b748..8eb0d7fa2e07 100644 --- a/AnkiDroid/src/main/res/values-cs/02-strings.xml +++ b/AnkiDroid/src/main/res/values-cs/02-strings.xml @@ -367,10 +367,10 @@ Kopírování se nezdařilo Nedostupné v režimu „Poznámky“ - %d card unburied - %d cards unburied - %d cards unburied - %d cards unburied + Zrušeno přeskočení %d karty + Zrušeno přeskočení %d karet + Zrušeno přeskočení %d karty + Zrušeno přeskočení %d karet Přemístit Record diff --git a/AnkiDroid/src/main/res/values-de/01-core.xml b/AnkiDroid/src/main/res/values-de/01-core.xml index b94a5013b7b6..7fdfa827669e 100644 --- a/AnkiDroid/src/main/res/values-de/01-core.xml +++ b/AnkiDroid/src/main/res/values-de/01-core.xml @@ -131,7 +131,7 @@ Stapelsuche Ungültiger Stapelname Glückwunsch! Das war alles für heute. - Deck finished for now! %s + Deck vorerst fertig! %s Es sind noch keine Karten fällig Gerätespeicher nicht eingebunden Synchronisieren diff --git a/AnkiDroid/src/main/res/values-de/04-network.xml b/AnkiDroid/src/main/res/values-de/04-network.xml index 5b0a16569bbc..a6a031426f3d 100644 --- a/AnkiDroid/src/main/res/values-de/04-network.xml +++ b/AnkiDroid/src/main/res/values-de/04-network.xml @@ -70,7 +70,7 @@ Synchronisation Vollsynchronisation des lokalen Stapels Sammlung synchronisiert - Collection synced. Media is being synced in the background. + Sammlung synchronisiert. Medien werden im Hintergrund synchronisiert. Ihre Datenbank ist beschädigt. Bitte reparieren Sie sie vor einem erneuten Synchronisationsversuch.\n\nBesuchen Sie %s für Informationen zum Reparieren Ihrer Datenbank. Lokal diff --git a/AnkiDroid/src/main/res/values-gu/04-network.xml b/AnkiDroid/src/main/res/values-gu/04-network.xml index b1a700c0b19e..366e52dc2936 100644 --- a/AnkiDroid/src/main/res/values-gu/04-network.xml +++ b/AnkiDroid/src/main/res/values-gu/04-network.xml @@ -48,38 +48,38 @@ તમે ઑફલાઇન છો સમન્વયન ભૂલ ભૂલ - Retry - Get shared decks - A network error has occurred + ફરીથી પ્રયત્ન કરો + વહેંચાયેલ ડેક મેળવો + નેટવર્ક ભૂલ આવી છે AnkiWeb માં લોગ ઇન કરો - You must log in to a third party account to use the cloud sync service. You can create one in the next step. + ક્લાઉડ સિંક સેવાનો ઉપયોગ કરવા માટે તમારે તૃતીય પક્ષ એકાઉન્ટમાં લૉગ ઇન કરવું આવશ્યક છે. તમે આગલા પગલામાં એક બનાવી શકો છો. ઈ - મેઈલ સરનામું પાસવર્ડ પ્રવેશ કરો - Don’t have an AnkiWeb account? It’s free! - Note: AnkiWeb is not affiliated with AnkiDroid - Sign up - Logged in as - Log out + AnkiWeb એકાઉન્ટ નથી? આ મફત છે! + નોંધ: AnkiWeb AnkiDroid સાથે જોડાયેલ નથી + સાઇન અપ કરો + તરીકે લૉગ ઇન કર્યું + લૉગ આઉટ =પાસવર્ડ રીસેટ કરો ઇમેઇલ ભૂલી ગયા છો? સાઇન ઇન કરી રહ્યાં છીએ - Options for XXX - Synchronization - Full sync from local - Collection synchronized - Collection synced. Media is being synced in the background. + XXX માટે વિકલ્પો + સિંક્રનાઇઝેશન + સ્થાનિક તરફથી સંપૂર્ણ સમન્વયન + સમન્વયિત સંગ્રહ + સમન્વયિત સંગ્રહ. મીડિયા પૃષ્ઠભૂમિમાં સમન્વયિત થઈ રહ્યું છે. Your database is corrupt. Please fix it before trying again to sync.\n\nSee %s for information about repairing your database. - Local - Remote - One-way sync - One way sync requested - The requested change will require a full upload of the database when you next synchronize your collection. If you have reviews or other changes waiting on another device that haven’t been synchronized here yet, they will be lost. Continue? - Due to a bug in the previously installed version of AnkiDroid, it’s recommended to force a full sync. + સ્થાનિક + દૂરસ્થ + વન-વે સિંક + વન-વે સિંકની વિનંતી કરી + જ્યારે તમે તમારા સંગ્રહને આગળ સિંક્રનાઇઝ કરશો ત્યારે વિનંતી કરેલ ફેરફારને ડેટાબેઝના સંપૂર્ણ અપલોડની જરૂર પડશે. જો તમારી પાસે અન્ય ઉપકરણ પર સમીક્ષાઓ અથવા અન્ય ફેરફારો રાહ જોઈ રહ્યાં છે જે હજી સુધી અહીં સમન્વયિત થયા નથી, તો તે ખોવાઈ જશે. ચાલુ રાખીએ? + AnkiDroid ના અગાઉ ઇન્સ્ટોલ કરેલ સંસ્કરણમાં બગને લીધે, સંપૂર્ણ સમન્વયન માટે દબાણ કરવાની ભલામણ કરવામાં આવે છે. - Sync (one-way) - Sync (log in) + સમન્વયન (એક-માર્ગી) + સમન્વયન (લોગ ઇન) diff --git a/AnkiDroid/src/main/res/values-gu/07-cardbrowser.xml b/AnkiDroid/src/main/res/values-gu/07-cardbrowser.xml index 4a4961e21cf2..0e7a6dd3370b 100644 --- a/AnkiDroid/src/main/res/values-gu/07-cardbrowser.xml +++ b/AnkiDroid/src/main/res/values-gu/07-cardbrowser.xml @@ -46,58 +46,58 @@ - %d card shown - %d cards shown + %d કાર્ડ બતાવ્યું + %d કાર્ડ બતાવ્યા - %d note shown - %d notes shown + %d નોંધ બતાવવામાં આવી + %d નોંધો બતાવવામાં આવી - All decks + બધા ડેક - Delete card - Delete cards + કાર્ડ કાઢી નાખો + કાર્ડ્સ કાઢી નાખો - Delete note - Delete notes + નોંધ કાઢી નાખો + નોંધો કાઢી નાખો - Change deck - Delete note? - Filter marked - Filter suspended - Filter by tag - Filter by flag - My searches - Save search - Choose a saved search - Name for the current search - You can’t save a search without a name - Name exists - Delete “%1$s”? - Change display order - Choose display order - Tags + ડેક બદલો + નોંધ કાઢી નાખીએ? + ફિલ્ટર ચિહ્નિત + ફિલ્ટર સસ્પેન્ડ કર્યું + ટેગ દ્વારા ફિલ્ટર કરો + ધ્વજ દ્વારા ફિલ્ટર કરો + મારી શોધ + શોધ સાચવો + સાચવેલી શોધ પસંદ કરો + વર્તમાન શોધ માટે નામ + તમે નામ વગર શોધ સાચવી શકતા નથી + નામ અસ્તિત્વમાં છે + “%1$s” કાઢી નાખીએ? + ડિસ્પ્લે ઓર્ડર બદલો + ડિસ્પ્લે ઓર્ડર પસંદ કરો + ટૅગ્સ - No sorting (faster) - By sort field - By created time - By note modification time - By card modification time - By due time - By interval - By ease - By reviews + કોઈ સૉર્ટિંગ નથી (ઝડપી) + સૉર્ટ ક્ષેત્ર દ્વારા + બનાવ્યા સુધીમાં + નોંધ ફેરફાર સમય દ્વારા + કાર્ડ ફેરફાર સમય દ્વારા + નિયત સમય સુધીમાં + અંતરાલ દ્વારા + સરળતા દ્વારા + સમીક્ષાઓ દ્વારા By lapses - Select all - Select none - (new) - (filtered) - (learning) - No cards found in deck ‘%s’ - Search all decks - Unknown + બધા પસંદ કરો + કોઈ પસંદ કરો + (નવું) + (ફિલ્ટર કરેલ) + (શીખવું) + ડેક \'%s\' માં કોઈ કાર્ડ મળ્યા નથી + બધા ડેક શોધો + અજ્ઞાત Truncate content Today is ‘0 %1$s’, tomorrow is ‘1 %2$s’, etc… diff --git a/AnkiDroid/src/main/res/values-gu/10-preferences.xml b/AnkiDroid/src/main/res/values-gu/10-preferences.xml index fd41f68ea3fb..effe759832fd 100644 --- a/AnkiDroid/src/main/res/values-gu/10-preferences.xml +++ b/AnkiDroid/src/main/res/values-gu/10-preferences.xml @@ -45,94 +45,94 @@ --> - Disabled + અક્ષમ - %d min - %d mins + %d મિનિટ + %d મિનિટ %s ms - No results + કોઈ પરિણામ નથી - General - Studying - System-wide - Reviewing + જનરલ + અભ્યાસ + સિસ્ટમ-વ્યાપી + સમીક્ષા કરી રહ્યા છીએ Sync Scheduling - Whiteboard + વ્હાઇટબોર્ડ Appearance Themes Gestures - Controls - Advanced - Workarounds - Plugins + નિયંત્રણો + અદ્યતન + વર્કઅરાઉન્ડ + પ્લગઈન્સ Stroke width Type answer into the card Use a text input box inside the card to type in the answer - Reset languages - Reset language assignments (for text to speech and dictionaries) for all decks - Reset all language assignments? - All states reset - Card zoom - Image zoom + ભાષાઓ રીસેટ કરો + બધા ડેક માટે ભાષા સોંપણીઓ (ટેક્સ્ટ-ટુ-સ્પીચ અને શબ્દકોશ માટે) રીસેટ કરો + બધી ભાષા સોંપણીઓ રીસેટ કરીએ? + બધા રાજ્યો રીસેટ કરો + કાર્ડ ઝૂમ + છબી ઝૂમ Answer button size Card browser font scaling Display filenames in card browser Display media filenames in the card browser question/answer fields AnkiDroid directory Fullscreen mode - Off - Hide the system bars - Hide the system bars and answer buttons + બંધ + સિસ્ટમ બાર છુપાવો + સિસ્ટમ બાર અને જવાબ બટનો છુપાવો Answer buttons position - Top - Bottom - None + ટોપ + તળિયે + કોઈ નહિ - Enable gestures - Assign gestures to actions such as answering and editing cards. - 9-point touch - Allow touch gestures in screen corners - Full screen navigation drawer - Open navigation drawer when swiped right from anywhere on the screen - None - Swipe up - Swipe down - Swipe left - Swipe right - Double touch - Long touch - Touch top - Touch left - Touch right + હાવભાવ સક્ષમ કરો + જવાબ આપવા અને કાર્ડ સંપાદિત કરવા જેવી ક્રિયાઓ માટે હાવભાવ સોંપો. + 9-પોઇન્ટ ટચ + સ્ક્રીનના ખૂણામાં સ્પર્શ હાવભાવને મંજૂરી આપો + પૂર્ણ સ્ક્રીન નેવિગેશન ડ્રોઅર + સ્ક્રીન પર ગમે ત્યાંથી જમણે સ્વાઇપ કરવામાં આવે ત્યારે નેવિગેશન ડ્રોઅર ખોલો + કોઈ નથી + ઉપર સ્વાઇપ કરો + નીચે સ્વાઇપ કરો + ડાબે સ્વાઇપ કરો + જમણે સ્વાઇપ કરો + ડબલ ટચ + લાંબા સ્પર્શ + ટોચને સ્પર્શ કરો + ડાબે ટચ કરો + જમણે ટચ કરો Touch bottom - Touch top left - Touch top right - Touch middle center - Touch bottom left - Touch bottom right - Shake device - ‘%s’ Menu - Enables the ‘%s’ context menu globally - Double scrolling + ઉપર ડાબે ટચ કરો + ઉપર જમણી બાજુએ ટચ કરો + મધ્ય કેન્દ્રને સ્પર્શ કરો + નીચે ડાબી બાજુએ ટચ કરો + નીચે જમણે ટચ કરો + શેક ઉપકરણ + \'%s\' મેનૂ + વૈશ્વિક સ્તરે \'%s\' સંદર્ભ મેનૂને સક્ષમ કરે છે + ડબલ સ્ક્રોલિંગ Double the scroll gap with eReader Swipe sensitivity - Text to speech - Reads out question and answer if no sound file is included + ટેક્સ્ટ ટુ સ્પીચ + જો કોઈ ધ્વનિ ફાઇલ શામેલ ન હોય તો પ્રશ્ન અને જવાબ વાંચે છે Fetch media on sync AnkiWeb account - Not logged in + લૉગ ઇન નથી Automatic synchronization Sync automatically on app start/exit if the last sync was more than 10 minutes ago. Always - Only on unmetered connections - Never + માત્ર મીટર વગરના જોડાણો પર + ક્યારેય Display synchronization status Change the sync icon when changes can be uploaded Allow sync on metered connections @@ -140,20 +140,20 @@ Frequency Lifetime Theme - Day theme - Night theme - Language - System language + દિવસની થીમ + નાઇટ થીમ + ભાષા + સિસ્ટમ ભાષા Notifications Notify when Never notify Pending messages available More than %d cards due Vibrate - Blink light - Automatic display answer + ઝબકતો પ્રકાશ + આપોઆપ પ્રદર્શન જવાબ Show answer automatically without user input. Configure from deck options. - Select language + ભાષા પસંદ કરો Disable card hardware render Hardware render is faster but may have problems, specifically on Android 8/8.1. If you cannot see parts of the card review user interface, try this setting. Safe display mode @@ -167,7 +167,7 @@ A second tap of the answer buttons will be ignored if this time has not elapsed. This prevents accidental double taps Show answer long-press time Minimum pressing time before the show answer button registers a touch. - Show button time + સમય બતાવો બટન Show next review time on answer buttons Show large answer buttons Show answer button in 2 rows @@ -222,21 +222,21 @@ Sync url Keyboard - Bluetooth - Answer buttons - Card - Note - Navigation - Media - Misc + બ્લુટુથ + જવાબ બટનો + કાર્ડ + નૉૅધ + સંશોધક + મીડિયા + વિવિધ - Select tags + ટૅગ્સ પસંદ કરો - General - Reminders - Filter + જનરલ + રીમાઇન્ડર્સ + ફિલ્ટર કરો Search - Limit to + સુધીની મર્યાદા cards selected by Reschedule Reschedule cards based on my answers in this deck @@ -270,13 +270,13 @@ Move a joystick/motion controller User actions Trigger JavaScript from the review screen - User action 1 - User action 2 - User action 3 - User action 4 - User action 5 - User action 6 - User action 7 + વપરાશકર્તા ક્રિયા 1 + વપરાશકર્તા ક્રિયા 2 + વપરાશકર્તા ક્રિયા 3 + વપરાશકર્તા ક્રિયા 4 + વપરાશકર્તા ક્રિયા 5 + વપરાશકર્તા ક્રિયા 6 + વપરાશકર્તા ક્રિયા 7 User action 8 User action 9 @@ -330,9 +330,9 @@ Delete unused media files Delete images and other media that are not prefixed with _ and are not referenced by any notes - Delete unused media files + ન વપરાયેલ મીડિયા ફાઇલો કાઢી નાખો - Delete backups + બેકઅપ કાઢી નાખો Delete backups Deleting backups… diff --git a/AnkiDroid/src/main/res/values-gu/11-arrays.xml b/AnkiDroid/src/main/res/values-gu/11-arrays.xml index 590190139b97..12e4d2025265 100644 --- a/AnkiDroid/src/main/res/values-gu/11-arrays.xml +++ b/AnkiDroid/src/main/res/values-gu/11-arrays.xml @@ -52,26 +52,26 @@ સૌથી જૂનું પ્રથમ જોયું રેન્ડમ - Increasing intervals - Decreasing intervals - Most lapsed - Order added + અંતરાલો વધારો + ઘટતા અંતરાલ + મોટા ભાગના લેપ્સ + ઓર્ડર ઉમેર્યો Order due - Latest added first + સૌથી નવું પ્રથમ ઉમેર્યું Relative overdueness - Use current deck + વર્તમાન ડેકનો ઉપયોગ કરો Decide by note type - Follow system + સિસ્ટમ અનુસરો - Light - Plain + પ્રકાશ + સાદો - Black - Dark + કાળો + અંધકાર - xx-small + xx-નાનું x-small નાનું મધ્યમ @@ -85,21 +85,21 @@ Answer easy Play media Abort learning - Toggle Red Flag - Toggle Orange Flag - Toggle Green Flag - Toggle Blue Flag - Toggle Pink Flag - Toggle Turquoise Flag - Toggle Purple Flag - Remove Flag + લાલ ધ્વજને ટૉગલ કરો + નારંગી ધ્વજને ટૉગલ કરો + લીલો ધ્વજ ટૉગલ કરો + વાદળી ધ્વજ ટૉગલ કરો + ગુલાબી ધ્વજને ટૉગલ કરો + પીરોજ ધ્વજને ટૉગલ કરો + જાંબલી ધ્વજને ટૉગલ કરો + ધ્વજ દૂર કરો Page Up Page Down Abort Learning and Sync - Toggle Whiteboard - Show Hint - Show All Hints - Record Voice - Replay Voice - Save Recording + વ્હાઇટબોર્ડ ટૉગલ કરો + સંકેત બતાવો + બધા સંકેતો બતાવો + અવાજ રેકોર્ડ કરો + અવાજ ફરી ચલાવો + રેકોર્ડિંગ સાચવો diff --git a/AnkiDroid/src/main/res/values-gu/16-multimedia-editor.xml b/AnkiDroid/src/main/res/values-gu/16-multimedia-editor.xml index de9af0328af3..b83072da80cb 100644 --- a/AnkiDroid/src/main/res/values-gu/16-multimedia-editor.xml +++ b/AnkiDroid/src/main/res/values-gu/16-multimedia-editor.xml @@ -40,52 +40,52 @@ --> - Add image - Add audio clip - Add video clip - Record audio - Advanced editor + છબી ઉમેરો + ઓડિયો ક્લિપ ઉમેરો + વિડિઓ ક્લિપ ઉમેરો + ઓડિયો રેકોર્ડ કરો + અદ્યતન સંપાદક Cloze deletion - Text - Image - Audio recording - Audio Clip - Done + ટેક્સ્ટ + છબી + ઓડિયો રેકોર્ડિંગ + ઓડિયો ક્લિપ + થઈ ગયું - Clear - Clone from + ચોખ્ખુ + માંથી ક્લોન - Take from + પાસેથી લો - Gallery - Camera - Audio - Video + ગેલેરી + કેમેરા + ઓડિયો + વિડિયો - Something went wrong - SVGs are not available for preview - Error converting clipboard image to png: %s - Attach multimedia content to the %1$s field - Attach media + કંઈક ખોટું થયું + SVG પૂર્વાવલોકન માટે ઉપલબ્ધ નથી + ક્લિપબોર્ડ છબીને png માં રૂપાંતરિત કરવામાં ભૂલ: %s + %1$s ફીલ્ડમાં મલ્ટીમીડિયા સામગ્રી ઉમેરો + મીડિયા જોડો - Recording failed - Playing failed - Unable to create recorder tool bar + રેકોર્ડિંગ નિષ્ફળ થયું + રમવામાં નિષ્ફળ + રેકોર્ડર ટૂલ બાર બનાવવામાં અસમર્થ - Editing field + સંપાદન ક્ષેત્ર - Do you want to crop this image? - Crop image - Current image size is %sMB. Default image size limit is 1MB. Do you want to crop it? + શું તમે આ છબી કાપવા માંગો છો? + છબીને કાપો + વર્તમાન છબીનું કદ %sMB છે. ડિફૉલ્ટ છબી કદ મર્યાદા 1MB છે. શું તમે તેને કાપવા માંગો છો? "Select image failed, Please retry" App returned an unexpected value. You may need to use a different app Field Contents diff --git a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml index 091e34422252..ce66c60f8a6c 100644 --- a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml @@ -203,7 +203,7 @@ %d 秒後に自動同期がスタートします。 - データ通信量の消費によって、通信事業者(携帯会社など)への支払い料金が増える場合があります。 + データ通信の使用によって、通信事業者(携帯電話会社など)への支払い料金が増える場合があります。 このデッキ内の、今日出題する予定の新規カードの数。 このデッキ内の、今日出題する予定のカードの数。 このデッキ内の、習得中カードの数。 diff --git a/AnkiDroid/src/main/res/values-ja/10-preferences.xml b/AnkiDroid/src/main/res/values-ja/10-preferences.xml index a2620a704217..52634ed1707a 100644 --- a/AnkiDroid/src/main/res/values-ja/10-preferences.xml +++ b/AnkiDroid/src/main/res/values-ja/10-preferences.xml @@ -194,7 +194,7 @@ 既定値にリセット 初期設定にリセットしますか? リセット - サードパーティ製APIアプリ + サードパーティー製APIアプリ 辞書やユーティリティなど、AnkiDroidを活用するアプリのリストを見るにはここをタップしてください 学習画面 diff --git a/AnkiDroid/src/main/res/values-mr/02-strings.xml b/AnkiDroid/src/main/res/values-mr/02-strings.xml index f8b2405b7953..1cae73acefc6 100644 --- a/AnkiDroid/src/main/res/values-mr/02-strings.xml +++ b/AnkiDroid/src/main/res/values-mr/02-strings.xml @@ -132,7 +132,7 @@ - %1$d minute + %1$d मिनिटे %1$d मिनिटे AnkiDroid kārḍa @@ -363,7 +363,7 @@ %d cards unburied Reposition - Record + रेकॉर्ड थांबा खेळा पुढे diff --git a/AnkiDroid/src/main/res/values-mr/03-dialogs.xml b/AnkiDroid/src/main/res/values-mr/03-dialogs.xml index 8c670a6f630f..93e555f566bd 100644 --- a/AnkiDroid/src/main/res/values-mr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mr/03-dialogs.xml @@ -86,20 +86,20 @@ सानुकूल अभ्यास डेक पुन्हा तयार करू शकलो नाही Storage full Storage almost full - No space - AnkiDroid needs %s free storage space to continue. Please clear some space + जागा नाही + AnkiDroid ला सुरू ठेवण्यासाठी %s विनामूल्य स्टोरेज स्पेस आवश्यक आहे. कृपया थोडी जागा द्या बॅकअप पुनर्संचयित? आपला संग्रह जुन्या प्रतीसह पुनर्स्थित केला जाईल. कोणतीही जतन न केलेली प्रगती गमावली जाईल. - Choose another + दुसरा निवडा रद्द करा ठीक आहे - Confirm + पुष्टी नाही होय - Keep - Remove + ठेवा + काढा सुरू - Processing… + प्रक्रिया करत आहे… तयार करा हटवा @@ -174,7 +174,7 @@ स्मरणपत्रे शेड्यूल करण्यात अयशस्वी बरीच स्मरणपत्रे शेड्यूल केली. काही दिसणार नाहीत - Set Language + भाषा सेट करा मजकूर संपादित करताना जीबीआर्ड बदलणारी भाषा समर्थन करणारे काही बहुभाषिक कीबोर्ड \n\n कृपया आपला कीबोर्ड भाषा बदलत नसेल तर आपल्या कीबोर्ड निर्मात्याकडून “setImeHintLocales” वैशिष्ट्याची विनंती करा. AnkiDroid वापरणे @@ -190,26 +190,26 @@ विकसित करा दर इतर - Translate + भाषांतर करा समुदाय अंकी मंच विघटन फेसबुक ट्विटर - Privacy - AnkiDroid Privacy Policy - AnkiWeb Privacy Policy - AnkiWeb Terms and Conditions + गोपनीयता + AnkiDroid गोपनीयता धोरण + AnkiWeb गोपनीयता धोरण + AnkiWeb अटी आणि नियम समस्यानिवारण अहवाल पाठवा अहवाल आधीच सादर केला आहे - Report was sent! + अहवाल पाठवला! An automatic sync may be triggered in %d second स्वयंचलित समक्रमण %d सेकंदात ट्रिगर केले जाऊ शकते - Your internet provider may charge money for data use - Number of new cards to see today in this deck. + तुमचा इंटरनेट प्रदाता डेटा वापरासाठी पैसे आकारू शकतो + या डेकमध्ये आज पाहण्यासाठी नवीन कार्डांची संख्या. Number of cards due today in this deck. Number of cards in learning in this deck. डिसेबल केले - %d min - %d mins + %d मि + %d मिनिटे - %s ms + %s मिस - No results + कोणतेही परिणाम नाहीत - General - Studying - System-wide + सामान्य + अभ्यास करत आहे + प्रणाली-व्यापी पुनरावलोकन करत आहे - Sync - Scheduling + सिंक + शेड्युलिंग व्हाइटबोर्ड व्हाइटबोर्ड थीम्स जेश्चर - Controls + नियंत्रणे आधुनिक वर्कराउंड्स प्लगइन @@ -105,7 +105,7 @@ डावीकडे स्वाइप करा उजवीकडे स्वाइप करा दुहेरी स्पर्श - Long touch + लांब स्पर्श शीर्षस्थानी स्पर्श करा डावीकडे स्पर्श करा उजवीकडे स्पर्श करा @@ -115,7 +115,7 @@ मध्यभागी मध्यभागी स्पर्श करा डावीकडे तळाशी स्पर्श करा उजवीकडे तळाशी स्पर्श करा - Shake device + शेक डिव्हाइस ‘%s’ मेनू जागतिक स्तरावर ‘%s’ संदर्भ मेनू सक्षम करते डबल स्क्रोलिंग @@ -126,15 +126,15 @@ Fetch media on sync AnkiWeb account - Not logged in - Automatic synchronization + लॉग इन नाही + स्वयंचलित सिंक्रोनाइझेशन Sync automatically on app start/exit if the last sync was more than 10 minutes ago. Always - Only on unmetered connections - Never - Display synchronization status - Change the sync icon when changes can be uploaded + केवळ मीटर नसलेल्या कनेक्शनवर + कधीही + सिंक्रोनाइझेशन स्थिती प्रदर्शित करा + जेव्हा बदल अपलोड केले जाऊ शकतात तेव्हा सिंक चिन्ह बदला Allow sync on metered connections If disabled, you will be warned if you try to sync on a metered connection Frequency @@ -219,20 +219,20 @@ If not set, the default AnkiWeb server will be used instead. Learn more ]]> - Sync url + url समक्रमित करा - Keyboard - Bluetooth - Answer buttons - Card - Note - Navigation - Media + कीबोर्ड + ब्लूटूथ + उत्तर बटणे + कार्ड + नोंद + नेव्हिगेशन + मीडिया Misc - Select tags + टॅग निवडा - General + सामान्य Reminders फिल्टर करा शोधा @@ -254,7 +254,7 @@ पुनरावलोकनकर्त्यामध्ये स्वयंचलितपणे ‘इनपुट टाईप’ फील्डवर लक्ष केंद्रित करा चेंजलॉग उघडा - About + बद्दल Contributors contributors. You can help AnkiDroid too by programming, translating, donating and more!]]> License @@ -263,22 +263,22 @@ Add gesture Replace gesture - Add key - Replace key - Press a key - Add joystick/motion controller + की जोडा + की बदला + एक कळ दाबा + जॉयस्टिक/मोशन कंट्रोलर जोडा Move a joystick/motion controller User actions Trigger JavaScript from the review screen - User action 1 - User action 2 - User action 3 - User action 4 - User action 5 - User action 6 - User action 7 - User action 8 - User action 9 + वापरकर्ता क्रिया 1 + वापरकर्ता क्रिया 2 + वापरकर्ता क्रिया 3 + वापरकर्ता क्रिया 4 + वापरकर्ता क्रिया 5 + वापरकर्ता क्रिया 6 + वापरकर्ता क्रिया 7 + वापरकर्ता क्रिया 8 + वापरकर्ता क्रिया 9 Select card side Question @@ -288,7 +288,7 @@ A: %s %s - Remove ‘%s’ + \'%s\' काढा Already bound to ‘%s’ Experimental @@ -332,9 +332,9 @@ Delete images and other media that are not prefixed with _ and are not referenced by any notes Delete unused media files - Delete backups - Delete backups - Deleting backups… + बॅकअप हटवा + बॅकअप हटवा + बॅकअप हटवत आहे… Delete collection Delete collection, media, and backups. App settings are not deleted @@ -347,9 +347,9 @@ Delete everything Are you sure you want to delete all data? This includes your collection, media, backups and preferences.\n\nNote: this action will close the window. - Delete app data - Delete settings and other app data - Delete app data + ॲप डेटा हटवा + सेटिंग्ज आणि इतर ॲप डेटा हटवा + ॲप डेटा हटवा Are you sure you want to delete app data? This includes settings and other app data.\n\nNote: this action will close the window. - Answer again - Answer hard + पुन्हा उत्तर द्या + कठोर उत्तर द्या Answer good - Answer easy + सहज उत्तर द्या मीडिया प्ले करा शिक्षण रद्द करा लाल ध्वज टॉगल करा ऑरेंज ध्वज टॉगल करा ग्रीन ध्वज टॉगल करा निळा ध्वज टॉगल करा - Toggle Pink Flag - Toggle Turquoise Flag - Toggle Purple Flag + गुलाबी ध्वज टॉगल करा + पिरोजा ध्वज टॉगल करा + जांभळा ध्वज टॉगल करा ध्वज काढा पृष्ठ वर पृष्ठ खाली निरस्त शिक्षण आणि संकालन व्हाईटबोर्ड टॉगल करा - Show Hint + इशारा दर्शवा Show All Hints आवाज रेकॉर्ड करा आवाज पुन्हा प्ले करा - Save Recording + रेकॉर्डिंग जतन करा diff --git a/AnkiDroid/src/main/res/values-mr/16-multimedia-editor.xml b/AnkiDroid/src/main/res/values-mr/16-multimedia-editor.xml index b368fc549d0c..b192934b8710 100644 --- a/AnkiDroid/src/main/res/values-mr/16-multimedia-editor.xml +++ b/AnkiDroid/src/main/res/values-mr/16-multimedia-editor.xml @@ -42,7 +42,7 @@ प्रतिमा जोडा ऑडिओ क्लिप जोडा - Add video clip + व्हिडिओ क्लिप जोडा ऑडिओ रेकॉर्ड करा प्रगत संपादक क्लोज हटविणे @@ -66,13 +66,13 @@ गॅलरी कॅमेरा - Audio - Video + ऑडिओ + व्हिडिओ काहीतरी चूक झाली - SVGs are not available for preview - Error converting clipboard image to png: %s + SVGs पूर्वावलोकनासाठी उपलब्ध नाहीत + क्लिपबोर्ड प्रतिमा png मध्ये रूपांतरित करताना त्रुटी: %s %1$s फील्डमध्ये मल्टीमीडिया सामग्री जोडा मीडिया संलग्न करा From 0439663a69ebe3a12087e2aca060817b23c81bfd Mon Sep 17 00:00:00 2001 From: Ashish Yadav <48384865+criticalay@users.noreply.github.com> Date: Mon, 22 Apr 2024 14:49:37 +0530 Subject: [PATCH 086/138] feat(card-browser): rename flags Done in the Card Browser options Fixes 16205 --- .../src/main/java/com/ichi2/anki/Flag.kt | 16 +++ .../anki/dialogs/BrowserOptionsDialog.kt | 9 ++ .../com/ichi2/anki/dialogs/FlagAdapter.kt | 136 ++++++++++++++++++ .../ichi2/anki/dialogs/FlagRenameDialog.kt | 113 +++++++++++++++ .../res/layout/browser_options_dialog.xml | 36 +++++ .../src/main/res/layout/edit_flag_item.xml | 86 +++++++++++ .../main/res/layout/rename_flag_layout.xml | 27 ++++ AnkiDroid/src/main/res/values/01-core.xml | 1 + AnkiDroid/src/main/res/values/03-dialogs.xml | 3 + 9 files changed, 427 insertions(+) create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagAdapter.kt create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagRenameDialog.kt create mode 100644 AnkiDroid/src/main/res/layout/edit_flag_item.xml create mode 100644 AnkiDroid/src/main/res/layout/rename_flag_layout.xml diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt b/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt index 503baf3ee4a3..b45af7a8697d 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt @@ -57,6 +57,16 @@ enum class Flag(val code: Int, @DrawableRes val drawableRes: Int, @ColorRes val PURPLE -> TR.actionsFlagPurple() } + /** + * Renames the flag + * + * @param newName The new name for the flag. + */ + suspend fun rename(newName: String) { + val labels = FlagLabels.loadFromColConfig() + labels.updateName(this, newName) + } + companion object { fun fromCode(code: Int): Flag { return entries.first { it.code == code } @@ -85,6 +95,12 @@ private value class FlagLabels(val value: JSONObject) { * This is not supported for [Flag.NONE] and is validated outside this method */ fun getLabel(flag: Flag): String? = value.getStringOrNull(flag.code.toString()) + suspend fun updateName(flag: Flag, newName: String) { + value.put(flag.ordinal.toString(), newName) + withCol { + config.set("flagLabels", value) + } + } companion object { suspend fun loadFromColConfig() = diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/BrowserOptionsDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/BrowserOptionsDialog.kt index 2c42ac83b891..924c9c743b3e 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/BrowserOptionsDialog.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/BrowserOptionsDialog.kt @@ -21,6 +21,7 @@ import android.content.DialogInterface import android.os.Bundle import android.view.View import android.widget.CheckBox +import android.widget.LinearLayout import android.widget.RadioButton import android.widget.RadioGroup import androidx.annotation.IdRes @@ -30,6 +31,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.ichi2.anki.R import com.ichi2.anki.browser.CardBrowserViewModel import com.ichi2.anki.model.CardsOrNotes +import timber.log.Timber class BrowserOptionsDialog(private val cardsOrNotes: CardsOrNotes, private val isTruncated: Boolean) : AppCompatDialogFragment() { private lateinit var dialogView: View @@ -61,6 +63,13 @@ class BrowserOptionsDialog(private val cardsOrNotes: CardsOrNotes, private val i dialogView.findViewById(R.id.truncate_checkbox).isChecked = isTruncated + dialogView.findViewById(R.id.action_rename_flag).setOnClickListener { + Timber.d("Rename flag clicked") + val flagRenameDialog = FlagRenameDialog() + flagRenameDialog.show(parentFragmentManager, "FlagRenameDialog") + dismiss() + } + return MaterialAlertDialogBuilder(requireContext()).run { this.setView(dialogView) this.setTitle(getString(R.string.browser_options_dialog_heading)) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagAdapter.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagAdapter.kt new file mode 100644 index 000000000000..e4c014a98df9 --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagAdapter.kt @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2024 Ashish Yadav + * + * 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 . + */ + +package com.ichi2.anki.dialogs + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.inputmethod.InputMethodManager +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.TextView +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.button.MaterialButton +import com.google.android.material.textfield.TextInputEditText +import com.ichi2.anki.Flag +import com.ichi2.anki.R +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +/** + * Adapter for the RecyclerView displaying flag items. + * + * @param lifecycleScope The CoroutineScope used for launching coroutines. + */ +class FlagAdapter(private val lifecycleScope: CoroutineScope) : + ListAdapter(FlagItemDiffCallback()) { + + inner class FlagViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val flagImageView: ImageView = itemView.findViewById(R.id.ic_flag) + val flagNameText: TextView = itemView.findViewById(R.id.flag_name) + val flagNameEdit: TextInputEditText = itemView.findViewById(R.id.flag_name_edit_text) + val editButton: MaterialButton = itemView.findViewById(R.id.action_edit_flag) + val saveButton: MaterialButton = itemView.findViewById(R.id.action_save_flag_name) + val cancelButton: MaterialButton = itemView.findViewById(R.id.action_cancel_flag_rename) + + val flagNameViewLayout: LinearLayout = itemView.findViewById(R.id.flag_name_view_layout) + val flagNameEditLayout: LinearLayout = itemView.findViewById(R.id.edit_flag_name_layout) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FlagViewHolder { + val view = + LayoutInflater.from(parent.context).inflate(R.layout.edit_flag_item, parent, false) + return FlagViewHolder(view) + } + + override fun onBindViewHolder(holder: FlagViewHolder, position: Int) { + val flagItem = getItem(position) + + holder.flagImageView.setImageResource(flagItem.icon) + + holder.flagNameEditLayout.visibility = View.GONE + + holder.flagNameText.text = flagItem.title + holder.flagNameEdit.setText(flagItem.title) + + holder.editButton.setOnClickListener { + flagItem.isInEditMode = true + holder.flagNameViewLayout.visibility = View.GONE + holder.flagNameEditLayout.visibility = View.VISIBLE + holder.flagNameEdit.requestFocus() + holder.flagNameEdit.text?.let { text -> holder.flagNameEdit.setSelection(text.length) } + val inputMethodManager = holder.flagNameEdit.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + inputMethodManager.showSoftInput(holder.flagNameEdit, InputMethodManager.SHOW_IMPLICIT) + } + + holder.saveButton.setOnClickListener { + val updatedTextName = holder.flagNameEdit.text.toString() + holder.flagNameViewLayout.visibility = View.VISIBLE + holder.flagNameEditLayout.visibility = View.GONE + val updatedFlagItem = flagItem.copy(title = updatedTextName) + val updatedDataset = currentList.toMutableList() + lifecycleScope.launch { + flagItem.renameTo(updatedTextName) + } + updatedFlagItem.isInEditMode = false + updatedDataset[position] = updatedFlagItem + submitList(updatedDataset) + } + + holder.cancelButton.setOnClickListener { + holder.flagNameViewLayout.visibility = View.VISIBLE + holder.flagNameEditLayout.visibility = View.GONE + flagItem.isInEditMode = false + } + } + + class FlagItemDiffCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: FlagItem, newItem: FlagItem): Boolean { + return oldItem.ordinal == newItem.ordinal + } + + override fun areContentsTheSame(oldItem: FlagItem, newItem: FlagItem): Boolean { + return oldItem.title == newItem.title + } + } +} + +/** + * Data class representing a flag item. + * + * @property ordinal The ordinal value of the flag. + * @property title The title or name of the flag. + * @property icon The icon resource ID of the flag. + * @property isInEditMode Whether the flag is being edited. + */ +data class FlagItem( + val ordinal: Int, + val title: String, + val icon: Int, + var isInEditMode: Boolean = false +) { + /** + * Renames the flag + * + * @param newName The new name for the flag. + */ + suspend fun renameTo(newName: String) = Flag.fromCode(ordinal).rename(newName) +} diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagRenameDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagRenameDialog.kt new file mode 100644 index 000000000000..ab86381101c5 --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagRenameDialog.kt @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2024 Ashish Yadav + * + * 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 . + */ + +package com.ichi2.anki.dialogs + +import android.app.Dialog +import android.content.DialogInterface +import android.os.Bundle +import android.view.WindowManager +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.DialogFragment +import androidx.lifecycle.lifecycleScope +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.ichi2.anki.Flag +import com.ichi2.anki.R +import com.ichi2.anki.showThemedToast +import com.ichi2.utils.customView +import com.ichi2.utils.negativeButton +import com.ichi2.utils.positiveButton +import com.ichi2.utils.title +import kotlinx.coroutines.launch +import timber.log.Timber + +/** + * A DialogFragment for renaming flags through a RecyclerView. + */ +class FlagRenameDialog : DialogFragment() { + private lateinit var recyclerView: RecyclerView + private lateinit var flagAdapter: FlagAdapter + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val dialogView = requireActivity().layoutInflater.inflate(R.layout.rename_flag_layout, null) + val builder = AlertDialog.Builder(requireContext()).apply { + customView(view = dialogView, 4, 4, 4, 4) + title(R.string.rename_flag) + // positiveButton is set in onResume so dialog is not always dismissed + positiveButton(R.string.dialog_ok, click = null) + negativeButton(R.string.dialog_cancel) + } + val dialog = builder.create() + + recyclerView = dialogView.findViewById(R.id.recyclerview_flags) + setupRecyclerView() + return dialog + } + + override fun onResume() { + super.onResume() + (dialog as AlertDialog).positiveButton.setOnClickListener { + // TODO: Extract pending changes from the adapter and save them + if (!::flagAdapter.isInitialized) return@setOnClickListener + val pendingChanges = flagAdapter.currentList.filter { it.isInEditMode } + if (pendingChanges.any()) { + Timber.i("Attempted to close with %d pending changes", pendingChanges.size) + showThemedToast(R.string.confirm_before_saving, true) + return@setOnClickListener + } + + Timber.i("Closing dialog", pendingChanges.size) + activity?.invalidateOptionsMenu() + dismiss() + } + } + + override fun onDismiss(dialog: DialogInterface) { + super.onDismiss(dialog) + activity?.invalidateOptionsMenu() + } + + override fun onStart() { + super.onStart() + dialog?.window?.clearFlags( + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + or WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM + ) + } + + private fun setupRecyclerView() = requireActivity().lifecycleScope.launch { + val flagItems = createFlagList() + flagAdapter = FlagAdapter(lifecycleScope = lifecycleScope) + recyclerView.adapter = flagAdapter + flagAdapter.submitList(flagItems) + recyclerView.layoutManager = LinearLayoutManager(requireContext()) + } + + private suspend fun createFlagList(): List { + Timber.d("Creating flag list") + return Flag.queryDisplayNames() + .filter { it.key != Flag.NONE } + .map { (flag, displayName) -> + FlagItem( + ordinal = flag.code, + title = displayName, + icon = flag.drawableRes + ) + } + } +} diff --git a/AnkiDroid/src/main/res/layout/browser_options_dialog.xml b/AnkiDroid/src/main/res/layout/browser_options_dialog.xml index 18be43a58002..4d175cac9c1a 100644 --- a/AnkiDroid/src/main/res/layout/browser_options_dialog.xml +++ b/AnkiDroid/src/main/res/layout/browser_options_dialog.xml @@ -2,6 +2,7 @@ + + + + + + + + + + + diff --git a/AnkiDroid/src/main/res/layout/edit_flag_item.xml b/AnkiDroid/src/main/res/layout/edit_flag_item.xml new file mode 100644 index 000000000000..9bdd40118d44 --- /dev/null +++ b/AnkiDroid/src/main/res/layout/edit_flag_item.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AnkiDroid/src/main/res/layout/rename_flag_layout.xml b/AnkiDroid/src/main/res/layout/rename_flag_layout.xml new file mode 100644 index 000000000000..58eb8d5704bf --- /dev/null +++ b/AnkiDroid/src/main/res/layout/rename_flag_layout.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/AnkiDroid/src/main/res/values/01-core.xml b/AnkiDroid/src/main/res/values/01-core.xml index c863c52eb9ac..7e2a59f4be0b 100644 --- a/AnkiDroid/src/main/res/values/01-core.xml +++ b/AnkiDroid/src/main/res/values/01-core.xml @@ -84,6 +84,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values/03-dialogs.xml b/AnkiDroid/src/main/res/values/03-dialogs.xml index dcb26acbb988..4f5fa9c1343b 100644 --- a/AnkiDroid/src/main/res/values/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values/03-dialogs.xml @@ -278,4 +278,7 @@ also changes the interval of the card" The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + + Confirm all changes before saving From ee8087338d050dd96f909f57d7ec3ba71c50a524 Mon Sep 17 00:00:00 2001 From: AnkiDroid Translations Date: Mon, 17 Jun 2024 17:22:51 +0000 Subject: [PATCH 087/138] Updated strings from Crowdin --- AnkiDroid/src/main/res/values-af/01-core.xml | 1 + AnkiDroid/src/main/res/values-af/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-am/01-core.xml | 1 + AnkiDroid/src/main/res/values-am/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ar/01-core.xml | 1 + AnkiDroid/src/main/res/values-ar/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-az/01-core.xml | 1 + AnkiDroid/src/main/res/values-az/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-be/01-core.xml | 1 + AnkiDroid/src/main/res/values-be/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-bg/01-core.xml | 1 + AnkiDroid/src/main/res/values-bg/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-bn/01-core.xml | 1 + AnkiDroid/src/main/res/values-bn/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ca/01-core.xml | 1 + AnkiDroid/src/main/res/values-ca/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ckb/01-core.xml | 1 + AnkiDroid/src/main/res/values-ckb/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-cs/01-core.xml | 1 + AnkiDroid/src/main/res/values-cs/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-da/01-core.xml | 1 + AnkiDroid/src/main/res/values-da/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-de/01-core.xml | 1 + AnkiDroid/src/main/res/values-de/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-el/01-core.xml | 1 + AnkiDroid/src/main/res/values-el/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-eo/01-core.xml | 1 + AnkiDroid/src/main/res/values-eo/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-es-rAR/01-core.xml | 1 + AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-es-rES/01-core.xml | 1 + AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-et/01-core.xml | 1 + AnkiDroid/src/main/res/values-et/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-eu/01-core.xml | 1 + AnkiDroid/src/main/res/values-eu/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-fa/01-core.xml | 1 + AnkiDroid/src/main/res/values-fa/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-fi/01-core.xml | 1 + AnkiDroid/src/main/res/values-fi/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-fil/01-core.xml | 1 + AnkiDroid/src/main/res/values-fil/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-fr/01-core.xml | 1 + AnkiDroid/src/main/res/values-fr/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-fy/01-core.xml | 1 + AnkiDroid/src/main/res/values-fy/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ga/01-core.xml | 1 + AnkiDroid/src/main/res/values-ga/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-gl/01-core.xml | 1 + AnkiDroid/src/main/res/values-gl/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-got/01-core.xml | 1 + AnkiDroid/src/main/res/values-got/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-gu/01-core.xml | 1 + AnkiDroid/src/main/res/values-gu/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-heb/01-core.xml | 1 + AnkiDroid/src/main/res/values-heb/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-hi/01-core.xml | 1 + AnkiDroid/src/main/res/values-hi/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-hr/01-core.xml | 1 + AnkiDroid/src/main/res/values-hr/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-hu/01-core.xml | 1 + AnkiDroid/src/main/res/values-hu/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-hy/01-core.xml | 1 + AnkiDroid/src/main/res/values-hy/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ind/01-core.xml | 1 + AnkiDroid/src/main/res/values-ind/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-is/01-core.xml | 1 + AnkiDroid/src/main/res/values-is/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-it/01-core.xml | 1 + AnkiDroid/src/main/res/values-it/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-iw/01-core.xml | 1 + AnkiDroid/src/main/res/values-iw/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ja/01-core.xml | 1 + AnkiDroid/src/main/res/values-ja/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-jv/01-core.xml | 1 + AnkiDroid/src/main/res/values-jv/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ka/01-core.xml | 1 + AnkiDroid/src/main/res/values-ka/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-kk/01-core.xml | 1 + AnkiDroid/src/main/res/values-kk/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-km/01-core.xml | 1 + AnkiDroid/src/main/res/values-km/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-kn/01-core.xml | 1 + AnkiDroid/src/main/res/values-kn/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ko/01-core.xml | 1 + AnkiDroid/src/main/res/values-ko/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ku/01-core.xml | 1 + AnkiDroid/src/main/res/values-ku/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ky/01-core.xml | 1 + AnkiDroid/src/main/res/values-ky/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-lt/01-core.xml | 1 + AnkiDroid/src/main/res/values-lt/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-lv/01-core.xml | 1 + AnkiDroid/src/main/res/values-lv/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-mk/01-core.xml | 1 + AnkiDroid/src/main/res/values-mk/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ml/01-core.xml | 1 + AnkiDroid/src/main/res/values-ml/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-mn/01-core.xml | 1 + AnkiDroid/src/main/res/values-mn/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-mr/01-core.xml | 1 + AnkiDroid/src/main/res/values-mr/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ms/01-core.xml | 1 + AnkiDroid/src/main/res/values-ms/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-my/01-core.xml | 1 + AnkiDroid/src/main/res/values-my/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-nl/01-core.xml | 1 + AnkiDroid/src/main/res/values-nl/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-nn/01-core.xml | 1 + AnkiDroid/src/main/res/values-nn/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-no/01-core.xml | 1 + AnkiDroid/src/main/res/values-no/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-or/01-core.xml | 1 + AnkiDroid/src/main/res/values-or/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-pa/01-core.xml | 1 + AnkiDroid/src/main/res/values-pa/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-pl/01-core.xml | 1 + AnkiDroid/src/main/res/values-pl/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-pt-rBR/01-core.xml | 1 + AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-pt-rPT/01-core.xml | 1 + AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ro/01-core.xml | 1 + AnkiDroid/src/main/res/values-ro/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ru/01-core.xml | 1 + AnkiDroid/src/main/res/values-ru/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sat/01-core.xml | 1 + AnkiDroid/src/main/res/values-sat/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sc/01-core.xml | 1 + AnkiDroid/src/main/res/values-sc/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sk/01-core.xml | 1 + AnkiDroid/src/main/res/values-sk/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sl/01-core.xml | 1 + AnkiDroid/src/main/res/values-sl/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sq/01-core.xml | 1 + AnkiDroid/src/main/res/values-sq/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sr/01-core.xml | 1 + AnkiDroid/src/main/res/values-sr/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ss/01-core.xml | 1 + AnkiDroid/src/main/res/values-ss/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sv/01-core.xml | 1 + AnkiDroid/src/main/res/values-sv/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-sw/01-core.xml | 1 + AnkiDroid/src/main/res/values-sw/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ta/01-core.xml | 1 + AnkiDroid/src/main/res/values-ta/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-te/01-core.xml | 1 + AnkiDroid/src/main/res/values-te/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-tg/01-core.xml | 1 + AnkiDroid/src/main/res/values-tg/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-tgl/01-core.xml | 1 + AnkiDroid/src/main/res/values-tgl/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-th/01-core.xml | 1 + AnkiDroid/src/main/res/values-th/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ti/01-core.xml | 1 + AnkiDroid/src/main/res/values-ti/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-tn/01-core.xml | 1 + AnkiDroid/src/main/res/values-tn/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-tr/01-core.xml | 1 + AnkiDroid/src/main/res/values-tr/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ts/01-core.xml | 1 + AnkiDroid/src/main/res/values-ts/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-tt/01-core.xml | 1 + AnkiDroid/src/main/res/values-tt/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-uk/01-core.xml | 1 + AnkiDroid/src/main/res/values-uk/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ur/01-core.xml | 1 + AnkiDroid/src/main/res/values-ur/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-uz/01-core.xml | 1 + AnkiDroid/src/main/res/values-uz/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-ve/01-core.xml | 1 + AnkiDroid/src/main/res/values-ve/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-vi/01-core.xml | 1 + AnkiDroid/src/main/res/values-vi/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-wo/01-core.xml | 1 + AnkiDroid/src/main/res/values-wo/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-xh/01-core.xml | 1 + AnkiDroid/src/main/res/values-xh/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-yue/01-core.xml | 1 + AnkiDroid/src/main/res/values-yue/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-zh-rCN/01-core.xml | 1 + AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-zh-rTW/01-core.xml | 1 + AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml | 2 ++ AnkiDroid/src/main/res/values-zu/01-core.xml | 1 + AnkiDroid/src/main/res/values-zu/03-dialogs.xml | 2 ++ 186 files changed, 279 insertions(+) diff --git a/AnkiDroid/src/main/res/values-af/01-core.xml b/AnkiDroid/src/main/res/values-af/01-core.xml index 590f319aad0a..9636e17884ee 100644 --- a/AnkiDroid/src/main/res/values-af/01-core.xml +++ b/AnkiDroid/src/main/res/values-af/01-core.xml @@ -104,6 +104,7 @@ Opskort Verwyder nota Merk + Rename flags Merk kaart Bewerk hegplaatjie Verwyder regtig hierdie nota en al die samegaande karte?\n%s diff --git a/AnkiDroid/src/main/res/values-af/03-dialogs.xml b/AnkiDroid/src/main/res/values-af/03-dialogs.xml index d5bce816b0e6..fc7327f21a86 100644 --- a/AnkiDroid/src/main/res/values-af/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-af/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-am/01-core.xml b/AnkiDroid/src/main/res/values-am/01-core.xml index a7c4ad222d5c..d9833f3293b9 100644 --- a/AnkiDroid/src/main/res/values-am/01-core.xml +++ b/AnkiDroid/src/main/res/values-am/01-core.xml @@ -104,6 +104,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-am/03-dialogs.xml b/AnkiDroid/src/main/res/values-am/03-dialogs.xml index 2d06df7413c3..d3f9afa52712 100644 --- a/AnkiDroid/src/main/res/values-am/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-am/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ar/01-core.xml b/AnkiDroid/src/main/res/values-ar/01-core.xml index e8976db7f8f3..9a2811b2c651 100644 --- a/AnkiDroid/src/main/res/values-ar/01-core.xml +++ b/AnkiDroid/src/main/res/values-ar/01-core.xml @@ -116,6 +116,7 @@ تعليق حذف الملحوظة أضف علما + Rename flags أضف علما للبطاقة تعديل الوسوم هل تريد حقًا حذف هذه الملحوظة وكل بطاقاتها؟\n%s diff --git a/AnkiDroid/src/main/res/values-ar/03-dialogs.xml b/AnkiDroid/src/main/res/values-ar/03-dialogs.xml index 0a800c6b71a6..416ac58c2f4a 100644 --- a/AnkiDroid/src/main/res/values-ar/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ar/03-dialogs.xml @@ -290,4 +290,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-az/01-core.xml b/AnkiDroid/src/main/res/values-az/01-core.xml index 08f9ec909dec..565497cad9dc 100644 --- a/AnkiDroid/src/main/res/values-az/01-core.xml +++ b/AnkiDroid/src/main/res/values-az/01-core.xml @@ -104,6 +104,7 @@ Dayandır Qeydi sil İşarələ + Rename flags İşarələnmiş kart Etiketlərə düzəliş et Bu qeyd və bütün kartlar həqiqətən də silinsin?\n%s diff --git a/AnkiDroid/src/main/res/values-az/03-dialogs.xml b/AnkiDroid/src/main/res/values-az/03-dialogs.xml index 205d8b402cf8..e62e1bb91134 100644 --- a/AnkiDroid/src/main/res/values-az/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-az/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-be/01-core.xml b/AnkiDroid/src/main/res/values-be/01-core.xml index bd17d588d950..d47be82ba7f5 100644 --- a/AnkiDroid/src/main/res/values-be/01-core.xml +++ b/AnkiDroid/src/main/res/values-be/01-core.xml @@ -110,6 +110,7 @@ Прыпыніць Выдаліць нататку Сцяжок + Rename flags Пазначыць картку Адрэдагаваць меткі Сапраўды выдаліць гэту нататку і ўсе яе карткі?\n%s diff --git a/AnkiDroid/src/main/res/values-be/03-dialogs.xml b/AnkiDroid/src/main/res/values-be/03-dialogs.xml index 9c712987d760..b1c6f5fe3520 100644 --- a/AnkiDroid/src/main/res/values-be/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-be/03-dialogs.xml @@ -276,4 +276,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-bg/01-core.xml b/AnkiDroid/src/main/res/values-bg/01-core.xml index 006fcdfe7681..04b36bd9929a 100644 --- a/AnkiDroid/src/main/res/values-bg/01-core.xml +++ b/AnkiDroid/src/main/res/values-bg/01-core.xml @@ -104,6 +104,7 @@ Спиране Изтрий бележка Знаме + Rename flags Маркиране на карта Редакция на етикети Наистина изтрий тази бележка и всичките и карти? \n%s diff --git a/AnkiDroid/src/main/res/values-bg/03-dialogs.xml b/AnkiDroid/src/main/res/values-bg/03-dialogs.xml index ed2ca2fde57e..6773d03c981f 100644 --- a/AnkiDroid/src/main/res/values-bg/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-bg/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-bn/01-core.xml b/AnkiDroid/src/main/res/values-bn/01-core.xml index 78c9641806eb..06164fe3f9d5 100644 --- a/AnkiDroid/src/main/res/values-bn/01-core.xml +++ b/AnkiDroid/src/main/res/values-bn/01-core.xml @@ -104,6 +104,7 @@ স্থগিত নোট মুছে ফেলুন ফ্ল্যাগ + Rename flags ফ্ল্যাগ কার্ড এডিট ফ্ল্যাগ সত্যি এই নোট এবং এর কার্ড মুছবেন? \n%s diff --git a/AnkiDroid/src/main/res/values-bn/03-dialogs.xml b/AnkiDroid/src/main/res/values-bn/03-dialogs.xml index 2decffbab229..9066799d2670 100644 --- a/AnkiDroid/src/main/res/values-bn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-bn/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ca/01-core.xml b/AnkiDroid/src/main/res/values-ca/01-core.xml index 72359707c0f5..49e980668bfc 100644 --- a/AnkiDroid/src/main/res/values-ca/01-core.xml +++ b/AnkiDroid/src/main/res/values-ca/01-core.xml @@ -104,6 +104,7 @@ Suspendre Suprimeix la nota Bandera + Rename flags Marcar tarjeta Edita etiquetes Segur que voleu suprimir aquesta nota i totes les seves fitxes?\n%s diff --git a/AnkiDroid/src/main/res/values-ca/03-dialogs.xml b/AnkiDroid/src/main/res/values-ca/03-dialogs.xml index b4bf13137ec2..3bb6368127a2 100644 --- a/AnkiDroid/src/main/res/values-ca/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ca/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ckb/01-core.xml b/AnkiDroid/src/main/res/values-ckb/01-core.xml index 8cc7e2253159..4358e5ee9edb 100644 --- a/AnkiDroid/src/main/res/values-ckb/01-core.xml +++ b/AnkiDroid/src/main/res/values-ckb/01-core.xml @@ -104,6 +104,7 @@ ڕاگرتن یادەشت ڕەشبکەوە ئاڵا + Rename flags کارتی ئاڵا Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml b/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml index 80664e9ae6c7..778ae2931f5c 100644 --- a/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-cs/01-core.xml b/AnkiDroid/src/main/res/values-cs/01-core.xml index 93a6ca42a016..f11fe4bd545d 100644 --- a/AnkiDroid/src/main/res/values-cs/01-core.xml +++ b/AnkiDroid/src/main/res/values-cs/01-core.xml @@ -110,6 +110,7 @@ Vyřadit Odstranit poznámku Příznak + Rename flags Příznak Upravit štítky Opravdu smazat poznámku a všechny její karty?\n%s diff --git a/AnkiDroid/src/main/res/values-cs/03-dialogs.xml b/AnkiDroid/src/main/res/values-cs/03-dialogs.xml index 42d7ba177171..c3b0b3d20b50 100644 --- a/AnkiDroid/src/main/res/values-cs/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-cs/03-dialogs.xml @@ -274,4 +274,6 @@ Open Systémový WebView je zastaralý. Některé funkce nebudou fungovat správně. Aktualizujte jej prosím.\n\nNainstalovaná verze: %1$d\nMinimální požadovaná verze: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-da/01-core.xml b/AnkiDroid/src/main/res/values-da/01-core.xml index 5ad0c320a90f..32a9f70f6030 100644 --- a/AnkiDroid/src/main/res/values-da/01-core.xml +++ b/AnkiDroid/src/main/res/values-da/01-core.xml @@ -104,6 +104,7 @@ Suspendér Slet note Markér + Rename flags Markér kort Redigér tags Vil du virkelig slette denne note og alle dens kort?\n%s diff --git a/AnkiDroid/src/main/res/values-da/03-dialogs.xml b/AnkiDroid/src/main/res/values-da/03-dialogs.xml index 3180bc04145c..1936d6405ac9 100644 --- a/AnkiDroid/src/main/res/values-da/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-da/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-de/01-core.xml b/AnkiDroid/src/main/res/values-de/01-core.xml index 7fdfa827669e..da8f710e9eed 100644 --- a/AnkiDroid/src/main/res/values-de/01-core.xml +++ b/AnkiDroid/src/main/res/values-de/01-core.xml @@ -104,6 +104,7 @@ Ausschließen Notiz löschen Flagge + Rename flags Karte markieren Schlagwörter bearbeiten Diese Notiz und alle ihre Karten tatsächlich löschen?\n%s diff --git a/AnkiDroid/src/main/res/values-de/03-dialogs.xml b/AnkiDroid/src/main/res/values-de/03-dialogs.xml index 04f813689248..b56a2c081e07 100644 --- a/AnkiDroid/src/main/res/values-de/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-de/03-dialogs.xml @@ -256,4 +256,6 @@ Offen Das System-WebView ist veraltet. Einige Funktionen werden nicht korrekt funktionieren. Bitte aktualisieren Sie es.\n\nInstallierte Version: %1$d\nMindestanforderung: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-el/01-core.xml b/AnkiDroid/src/main/res/values-el/01-core.xml index fb10de6dc7f0..96969934fc89 100644 --- a/AnkiDroid/src/main/res/values-el/01-core.xml +++ b/AnkiDroid/src/main/res/values-el/01-core.xml @@ -104,6 +104,7 @@ Αναστολή Διαγραφή Σημείωσης Σήμανση + Rename flags Σήμανση κάρτας Επεξεργασία ετικετών Πραγματικά να διαγραφεί αυτή η σημείωση και όλες οι κάρτες της;\n%s diff --git a/AnkiDroid/src/main/res/values-el/03-dialogs.xml b/AnkiDroid/src/main/res/values-el/03-dialogs.xml index 0417f5c2b24c..399b21ca757f 100644 --- a/AnkiDroid/src/main/res/values-el/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-el/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-eo/01-core.xml b/AnkiDroid/src/main/res/values-eo/01-core.xml index 01d14dc1c7a7..4c4ae59dbac6 100644 --- a/AnkiDroid/src/main/res/values-eo/01-core.xml +++ b/AnkiDroid/src/main/res/values-eo/01-core.xml @@ -104,6 +104,7 @@ Kaŝi daŭre Forigi noton Flagi + Rename flags Flagi karton Redakti etikedojn Ĉu vi certe volas forigi tiun ĉi noton kaj ĉiujn ĝiajn kartojn?\n%s diff --git a/AnkiDroid/src/main/res/values-eo/03-dialogs.xml b/AnkiDroid/src/main/res/values-eo/03-dialogs.xml index cc0419129514..086edebaaf18 100644 --- a/AnkiDroid/src/main/res/values-eo/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-eo/03-dialogs.xml @@ -258,4 +258,6 @@ Malfermi The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-es-rAR/01-core.xml b/AnkiDroid/src/main/res/values-es-rAR/01-core.xml index 7bc4263c8622..fb3649b6a7cc 100644 --- a/AnkiDroid/src/main/res/values-es-rAR/01-core.xml +++ b/AnkiDroid/src/main/res/values-es-rAR/01-core.xml @@ -104,6 +104,7 @@ Suspender Eliminar nota Marca + Rename flags Marcar tarjeta Editar etiquetas ¿Realmente eliminar esta nota y todas sus tarjetas?\n%s diff --git a/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml b/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml index 7127603dd726..6e99e3b59144 100644 --- a/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-es-rES/01-core.xml b/AnkiDroid/src/main/res/values-es-rES/01-core.xml index a39dd4a9ac5a..969e4f0daa6b 100644 --- a/AnkiDroid/src/main/res/values-es-rES/01-core.xml +++ b/AnkiDroid/src/main/res/values-es-rES/01-core.xml @@ -104,6 +104,7 @@ Suspender Eliminar nota Marca + Rename flags Marcar tarjeta Editar etiquetas ¿Realmente deseas eliminar esta nota y todas sus tarjetas?\n%s diff --git a/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml b/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml index 233e77890d32..5887b7e30b52 100644 --- a/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-et/01-core.xml b/AnkiDroid/src/main/res/values-et/01-core.xml index a57b8a021a2a..356462a410bf 100644 --- a/AnkiDroid/src/main/res/values-et/01-core.xml +++ b/AnkiDroid/src/main/res/values-et/01-core.xml @@ -104,6 +104,7 @@ Seiska Kustuta märge Lipp + Rename flags Pane kaardile lipp Muuda silte Kas tõesti kustutada see märge ja kõik selle kaardid?\n%s diff --git a/AnkiDroid/src/main/res/values-et/03-dialogs.xml b/AnkiDroid/src/main/res/values-et/03-dialogs.xml index ba25be3e26e8..341827ed8b2e 100644 --- a/AnkiDroid/src/main/res/values-et/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-et/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-eu/01-core.xml b/AnkiDroid/src/main/res/values-eu/01-core.xml index c32920eb0ed7..e0691d249f14 100644 --- a/AnkiDroid/src/main/res/values-eu/01-core.xml +++ b/AnkiDroid/src/main/res/values-eu/01-core.xml @@ -104,6 +104,7 @@ Suspend Ezabatu oharra Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-eu/03-dialogs.xml b/AnkiDroid/src/main/res/values-eu/03-dialogs.xml index e48ce0051554..133490926e26 100644 --- a/AnkiDroid/src/main/res/values-eu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-eu/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-fa/01-core.xml b/AnkiDroid/src/main/res/values-fa/01-core.xml index dbf465da3f2c..3636499557ec 100644 --- a/AnkiDroid/src/main/res/values-fa/01-core.xml +++ b/AnkiDroid/src/main/res/values-fa/01-core.xml @@ -104,6 +104,7 @@ تعلیق حذف یادداشت نشانه + Rename flags کارت های نشان شده ویرایش برچسب‌ها مطمئنید می خواهید این یادداشت و همه کارتهایش را پاک کنید؟\n%s diff --git a/AnkiDroid/src/main/res/values-fa/03-dialogs.xml b/AnkiDroid/src/main/res/values-fa/03-dialogs.xml index ed55abacb864..7d48136850b5 100644 --- a/AnkiDroid/src/main/res/values-fa/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fa/03-dialogs.xml @@ -256,4 +256,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-fi/01-core.xml b/AnkiDroid/src/main/res/values-fi/01-core.xml index c9f5a62a8a7d..5fee103f1aac 100644 --- a/AnkiDroid/src/main/res/values-fi/01-core.xml +++ b/AnkiDroid/src/main/res/values-fi/01-core.xml @@ -104,6 +104,7 @@ Keskeytä Poista merkintä Lippu + Rename flags Lisää lippu Muokkaa tageja Haluatko varmasti poistaa tämän merkinnän ja kaikki sen kortit?\n%s diff --git a/AnkiDroid/src/main/res/values-fi/03-dialogs.xml b/AnkiDroid/src/main/res/values-fi/03-dialogs.xml index c5d91ad7cd37..85e7c3ca9b0c 100644 --- a/AnkiDroid/src/main/res/values-fi/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fi/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-fil/01-core.xml b/AnkiDroid/src/main/res/values-fil/01-core.xml index 5dc6f743ef4c..74839d389773 100644 --- a/AnkiDroid/src/main/res/values-fil/01-core.xml +++ b/AnkiDroid/src/main/res/values-fil/01-core.xml @@ -104,6 +104,7 @@ Suspindihin Burahin ang tala Watawat + Rename flags Lagyan ng watawat ang card Baguhin ang mga tag Talaga bang gusto mong burahin ang talang ito at pati na rin ang lahat ngmga kard?\n%s diff --git a/AnkiDroid/src/main/res/values-fil/03-dialogs.xml b/AnkiDroid/src/main/res/values-fil/03-dialogs.xml index 43db4504ecf0..35eb92eb5fb4 100644 --- a/AnkiDroid/src/main/res/values-fil/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fil/03-dialogs.xml @@ -259,4 +259,6 @@ Mga file na may di-wastong pag-encode:%d Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-fr/01-core.xml b/AnkiDroid/src/main/res/values-fr/01-core.xml index 662de7d033ad..308bd05bcbd8 100644 --- a/AnkiDroid/src/main/res/values-fr/01-core.xml +++ b/AnkiDroid/src/main/res/values-fr/01-core.xml @@ -104,6 +104,7 @@ Suspendre Supprimer la note Ajouter un drapeau + Rename flags Ajouter un drapeau Modifier les étiquettes Voulez-vous vraiment supprimer cette note et toutes ses cartes ?\n%s diff --git a/AnkiDroid/src/main/res/values-fr/03-dialogs.xml b/AnkiDroid/src/main/res/values-fr/03-dialogs.xml index d4aa8c68cfe5..d9c937dd9ba6 100644 --- a/AnkiDroid/src/main/res/values-fr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fr/03-dialogs.xml @@ -256,4 +256,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-fy/01-core.xml b/AnkiDroid/src/main/res/values-fy/01-core.xml index 300700906895..a7d747a1b254 100644 --- a/AnkiDroid/src/main/res/values-fy/01-core.xml +++ b/AnkiDroid/src/main/res/values-fy/01-core.xml @@ -104,6 +104,7 @@ Suspend Memo fuortsmite Flag + Rename flags Flag card Edit tags Dizze memo en al syn kaarten fuortsmite?\n%s diff --git a/AnkiDroid/src/main/res/values-fy/03-dialogs.xml b/AnkiDroid/src/main/res/values-fy/03-dialogs.xml index 938497444a06..085319fbc070 100644 --- a/AnkiDroid/src/main/res/values-fy/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fy/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ga/01-core.xml b/AnkiDroid/src/main/res/values-ga/01-core.xml index 11024e3217f1..a6f227397140 100644 --- a/AnkiDroid/src/main/res/values-ga/01-core.xml +++ b/AnkiDroid/src/main/res/values-ga/01-core.xml @@ -113,6 +113,7 @@ Cuir ar fionraí Scrios nóta Bratach + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-ga/03-dialogs.xml b/AnkiDroid/src/main/res/values-ga/03-dialogs.xml index 11a0314a4b7b..477a1c94288b 100644 --- a/AnkiDroid/src/main/res/values-ga/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ga/03-dialogs.xml @@ -282,4 +282,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-gl/01-core.xml b/AnkiDroid/src/main/res/values-gl/01-core.xml index 743c6bf9e15e..382e9f2aaf3f 100644 --- a/AnkiDroid/src/main/res/values-gl/01-core.xml +++ b/AnkiDroid/src/main/res/values-gl/01-core.xml @@ -104,6 +104,7 @@ Suspender Eliminar nota Marca + Rename flags Tarxeta marcada Edit tags Tes a certeza de querer eliminar esta nota e todos os seus cartóns?\n%s diff --git a/AnkiDroid/src/main/res/values-gl/03-dialogs.xml b/AnkiDroid/src/main/res/values-gl/03-dialogs.xml index 4ddaa7e154ac..c0ee042cd0ca 100644 --- a/AnkiDroid/src/main/res/values-gl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-gl/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-got/01-core.xml b/AnkiDroid/src/main/res/values-got/01-core.xml index c33dff2c0af2..24ecf8960d23 100644 --- a/AnkiDroid/src/main/res/values-got/01-core.xml +++ b/AnkiDroid/src/main/res/values-got/01-core.xml @@ -104,6 +104,7 @@ Suspend Usnim melein Flag + Rename flags Flag card Edit tags Wileizu bi sunjai þo melein jah allos kartos is usniman?\n%s diff --git a/AnkiDroid/src/main/res/values-got/03-dialogs.xml b/AnkiDroid/src/main/res/values-got/03-dialogs.xml index f51b3a593f66..852d5173860a 100644 --- a/AnkiDroid/src/main/res/values-got/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-got/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-gu/01-core.xml b/AnkiDroid/src/main/res/values-gu/01-core.xml index 89602dcdc24b..7f539512c684 100644 --- a/AnkiDroid/src/main/res/values-gu/01-core.xml +++ b/AnkiDroid/src/main/res/values-gu/01-core.xml @@ -104,6 +104,7 @@ સસ્પેન્ડ નોંધ કાયમ માટે કાઢી નાખો ધ્વજ + Rename flags કાર્ડને ચિહ્નિત કરો ચિહ્નો બદલો આ નોંધ અને તેના તમામ કાડઁ ખરેખર કાઢી નાખીએ ?\n%s diff --git a/AnkiDroid/src/main/res/values-gu/03-dialogs.xml b/AnkiDroid/src/main/res/values-gu/03-dialogs.xml index 6548f5e0ba9a..909fc5817b47 100644 --- a/AnkiDroid/src/main/res/values-gu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-gu/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-heb/01-core.xml b/AnkiDroid/src/main/res/values-heb/01-core.xml index dc0824fa07fc..b09437783c78 100644 --- a/AnkiDroid/src/main/res/values-heb/01-core.xml +++ b/AnkiDroid/src/main/res/values-heb/01-core.xml @@ -111,6 +111,7 @@ הקפאה מחיקת רשומה דגל + Rename flags סימון כרטיס ערוך תגיות למחוק את הרשומה הזאת ואת כל הקלפים שלה?‏\n%s diff --git a/AnkiDroid/src/main/res/values-heb/03-dialogs.xml b/AnkiDroid/src/main/res/values-heb/03-dialogs.xml index c58e9db8c984..9a86ffa986be 100644 --- a/AnkiDroid/src/main/res/values-heb/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-heb/03-dialogs.xml @@ -273,4 +273,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-hi/01-core.xml b/AnkiDroid/src/main/res/values-hi/01-core.xml index 9b5ca9d62d17..f338cc52274b 100644 --- a/AnkiDroid/src/main/res/values-hi/01-core.xml +++ b/AnkiDroid/src/main/res/values-hi/01-core.xml @@ -104,6 +104,7 @@ निलंबित नोट हटाएँ ध्वज + Rename flags कार्ड को ध्वजांकित करें टैग संपादित करें वास्तव में इस नोट और उसके सभी cards?\n%s को हटाना diff --git a/AnkiDroid/src/main/res/values-hi/03-dialogs.xml b/AnkiDroid/src/main/res/values-hi/03-dialogs.xml index 8700986266b3..e2a2bb23ab81 100644 --- a/AnkiDroid/src/main/res/values-hi/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hi/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-hr/01-core.xml b/AnkiDroid/src/main/res/values-hr/01-core.xml index b8c274453680..b2358fa71c44 100644 --- a/AnkiDroid/src/main/res/values-hr/01-core.xml +++ b/AnkiDroid/src/main/res/values-hr/01-core.xml @@ -107,6 +107,7 @@ Obustavi Izbriši bilješku Označi + Rename flags Označi kartu Uredi oznake Zaista izbrisati ovu bilješku i sve njezine kartice?\n%s diff --git a/AnkiDroid/src/main/res/values-hr/03-dialogs.xml b/AnkiDroid/src/main/res/values-hr/03-dialogs.xml index 9472f65feb64..6826045d7a4a 100644 --- a/AnkiDroid/src/main/res/values-hr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hr/03-dialogs.xml @@ -266,4 +266,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-hu/01-core.xml b/AnkiDroid/src/main/res/values-hu/01-core.xml index fad6d8f75747..98c20cf27b7a 100644 --- a/AnkiDroid/src/main/res/values-hu/01-core.xml +++ b/AnkiDroid/src/main/res/values-hu/01-core.xml @@ -104,6 +104,7 @@ Felfüggesztés Jegyzet törlése Jelölő + Rename flags Kártya megjelölése Címkék szerkesztése Biztosan törölni akarod ezt a jegyzetet és az összes kártyáját?\n%s diff --git a/AnkiDroid/src/main/res/values-hu/03-dialogs.xml b/AnkiDroid/src/main/res/values-hu/03-dialogs.xml index caf4f1fcf52c..561ffb9238af 100644 --- a/AnkiDroid/src/main/res/values-hu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hu/03-dialogs.xml @@ -256,4 +256,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-hy/01-core.xml b/AnkiDroid/src/main/res/values-hy/01-core.xml index aabdb2c5eaae..6e117cc7f46c 100644 --- a/AnkiDroid/src/main/res/values-hy/01-core.xml +++ b/AnkiDroid/src/main/res/values-hy/01-core.xml @@ -104,6 +104,7 @@ Հեռացնել Ջնջել գրառումը Դրոշ + Rename flags Ավելացնել դրոշ Խմբագրել պիտակները Ջնջե՞լ այս գրառումը և նրա բոլոր քարտերը:\n%s diff --git a/AnkiDroid/src/main/res/values-hy/03-dialogs.xml b/AnkiDroid/src/main/res/values-hy/03-dialogs.xml index 3b5f4ff6369a..9e1427d1ea56 100644 --- a/AnkiDroid/src/main/res/values-hy/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hy/03-dialogs.xml @@ -256,4 +256,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ind/01-core.xml b/AnkiDroid/src/main/res/values-ind/01-core.xml index 4bb47aceb0a5..2164cdb0a7e9 100644 --- a/AnkiDroid/src/main/res/values-ind/01-core.xml +++ b/AnkiDroid/src/main/res/values-ind/01-core.xml @@ -101,6 +101,7 @@ Tangguhkan Hapus catatan Panji + Rename flags Beri kartu panji Edit tag Yakin akan menghapus catatan ini dan semua kartunya?\n%s diff --git a/AnkiDroid/src/main/res/values-ind/03-dialogs.xml b/AnkiDroid/src/main/res/values-ind/03-dialogs.xml index fb15d6525215..7a25a9456999 100644 --- a/AnkiDroid/src/main/res/values-ind/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ind/03-dialogs.xml @@ -250,4 +250,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-is/01-core.xml b/AnkiDroid/src/main/res/values-is/01-core.xml index 3247aa9565a7..138e24d3a994 100644 --- a/AnkiDroid/src/main/res/values-is/01-core.xml +++ b/AnkiDroid/src/main/res/values-is/01-core.xml @@ -104,6 +104,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-is/03-dialogs.xml b/AnkiDroid/src/main/res/values-is/03-dialogs.xml index 13b381bf73d2..192f20aa2d24 100644 --- a/AnkiDroid/src/main/res/values-is/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-is/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-it/01-core.xml b/AnkiDroid/src/main/res/values-it/01-core.xml index 391f9760c59d..a1be96ce79c6 100644 --- a/AnkiDroid/src/main/res/values-it/01-core.xml +++ b/AnkiDroid/src/main/res/values-it/01-core.xml @@ -104,6 +104,7 @@ Sospendi Elimina nota Bandiera + Rename flags Assegna bandiera Modifica etichette Vuoi veramente eliminare questa nota e tutte le sue carte?\n%s diff --git a/AnkiDroid/src/main/res/values-it/03-dialogs.xml b/AnkiDroid/src/main/res/values-it/03-dialogs.xml index ffd104fb259b..68159ad476b3 100644 --- a/AnkiDroid/src/main/res/values-it/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-it/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-iw/01-core.xml b/AnkiDroid/src/main/res/values-iw/01-core.xml index dc0824fa07fc..b09437783c78 100644 --- a/AnkiDroid/src/main/res/values-iw/01-core.xml +++ b/AnkiDroid/src/main/res/values-iw/01-core.xml @@ -111,6 +111,7 @@ הקפאה מחיקת רשומה דגל + Rename flags סימון כרטיס ערוך תגיות למחוק את הרשומה הזאת ואת כל הקלפים שלה?‏\n%s diff --git a/AnkiDroid/src/main/res/values-iw/03-dialogs.xml b/AnkiDroid/src/main/res/values-iw/03-dialogs.xml index c58e9db8c984..9a86ffa986be 100644 --- a/AnkiDroid/src/main/res/values-iw/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-iw/03-dialogs.xml @@ -273,4 +273,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ja/01-core.xml b/AnkiDroid/src/main/res/values-ja/01-core.xml index ff326af1ec29..5f4b8b329800 100644 --- a/AnkiDroid/src/main/res/values-ja/01-core.xml +++ b/AnkiDroid/src/main/res/values-ja/01-core.xml @@ -101,6 +101,7 @@ 休止 ノートを削除 フラグ + Rename flags カードにフラグを付ける タグを編集 このカードの元となるノートを削除してもよろしいですか? 同じノートから作られたカード(例:裏表反転カード)があれば、それらもすべて削除されます。\n%s diff --git a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml index ce66c60f8a6c..ecf2cb3ea625 100644 --- a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml @@ -249,4 +249,6 @@ 開く 「AndroidシステムのWebView 」(または「Android System WebView」)が古くなっています。いくつかの機能が正しく動作しません。更新してください。\n\nインストールされているバージョン: %1$d\n最低限必要なバージョン: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-jv/01-core.xml b/AnkiDroid/src/main/res/values-jv/01-core.xml index 637cb25a7de5..8dbd9c12516f 100644 --- a/AnkiDroid/src/main/res/values-jv/01-core.xml +++ b/AnkiDroid/src/main/res/values-jv/01-core.xml @@ -101,6 +101,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-jv/03-dialogs.xml b/AnkiDroid/src/main/res/values-jv/03-dialogs.xml index f1f35c733f05..0680d160e7ec 100644 --- a/AnkiDroid/src/main/res/values-jv/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-jv/03-dialogs.xml @@ -250,4 +250,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ka/01-core.xml b/AnkiDroid/src/main/res/values-ka/01-core.xml index e062eef8e5c1..a4e822adb23d 100644 --- a/AnkiDroid/src/main/res/values-ka/01-core.xml +++ b/AnkiDroid/src/main/res/values-ka/01-core.xml @@ -104,6 +104,7 @@ გამოტოვება შენიშვნის წაშლა დროშა + Rename flags დროშის მიმაგრება იარლიყის რედაქტირება ნამდვილად წავშალო ეს შენიშვნა და ყველა მისი ბარათი?\n%s diff --git a/AnkiDroid/src/main/res/values-ka/03-dialogs.xml b/AnkiDroid/src/main/res/values-ka/03-dialogs.xml index 44c11864667c..03edf32d5617 100644 --- a/AnkiDroid/src/main/res/values-ka/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ka/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-kk/01-core.xml b/AnkiDroid/src/main/res/values-kk/01-core.xml index 78823cdc542f..df49724922e6 100644 --- a/AnkiDroid/src/main/res/values-kk/01-core.xml +++ b/AnkiDroid/src/main/res/values-kk/01-core.xml @@ -104,6 +104,7 @@ Suspend Жазба жою Бөлектеу + Rename flags Картаны бөлектеу Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-kk/03-dialogs.xml b/AnkiDroid/src/main/res/values-kk/03-dialogs.xml index 28ab9ec10660..f0e28ffe2bbe 100644 --- a/AnkiDroid/src/main/res/values-kk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-kk/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-km/01-core.xml b/AnkiDroid/src/main/res/values-km/01-core.xml index 588304dfd43a..e7ffb1997024 100644 --- a/AnkiDroid/src/main/res/values-km/01-core.xml +++ b/AnkiDroid/src/main/res/values-km/01-core.xml @@ -101,6 +101,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-km/03-dialogs.xml b/AnkiDroid/src/main/res/values-km/03-dialogs.xml index 110351f03a39..eed6bb7903c4 100644 --- a/AnkiDroid/src/main/res/values-km/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-km/03-dialogs.xml @@ -250,4 +250,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-kn/01-core.xml b/AnkiDroid/src/main/res/values-kn/01-core.xml index 40d1f2b13b29..fd5f3d54cf91 100644 --- a/AnkiDroid/src/main/res/values-kn/01-core.xml +++ b/AnkiDroid/src/main/res/values-kn/01-core.xml @@ -104,6 +104,7 @@ ಅಮಾನತ್ತುಗೊಳಿಸು ಟಿಪ್ಪಣಿ ಅಳಿಸಿ ಧ್ವಜ + Rename flags ಫ್ಲ್ಯಾಗ್ ಕಾರ್ಡ್ ಟ್ಯಾಗ್‌ಗಳನ್ನು ಸಂಪಾದಿಸಿ ಈ ಟಿಪ್ಪಣಿ ಮತ್ತು ಅದರ ಎಲ್ಲಾ ಕಾರ್ಡ್‌ಗಳನ್ನು ನಿಜವಾಗಿಯೂ ಅಳಿಸಿ? \n%s diff --git a/AnkiDroid/src/main/res/values-kn/03-dialogs.xml b/AnkiDroid/src/main/res/values-kn/03-dialogs.xml index fef2942cbeb0..6133fd3b10d7 100644 --- a/AnkiDroid/src/main/res/values-kn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-kn/03-dialogs.xml @@ -256,4 +256,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ko/01-core.xml b/AnkiDroid/src/main/res/values-ko/01-core.xml index d55e6cea2a5a..ce336ba6a544 100644 --- a/AnkiDroid/src/main/res/values-ko/01-core.xml +++ b/AnkiDroid/src/main/res/values-ko/01-core.xml @@ -101,6 +101,7 @@ 비활성화 노트 삭제하기 표시 + Rename flags 카드에 플래그 추가 태그 수정 다음 노트와 그 노트의 모든 카드를 정말로 삭제하시겠습니까?\n%s diff --git a/AnkiDroid/src/main/res/values-ko/03-dialogs.xml b/AnkiDroid/src/main/res/values-ko/03-dialogs.xml index c6897836dff6..a4d4cd6b3c46 100644 --- a/AnkiDroid/src/main/res/values-ko/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ko/03-dialogs.xml @@ -250,4 +250,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ku/01-core.xml b/AnkiDroid/src/main/res/values-ku/01-core.xml index df9e32d6d02d..44e3a5e7e855 100644 --- a/AnkiDroid/src/main/res/values-ku/01-core.xml +++ b/AnkiDroid/src/main/res/values-ku/01-core.xml @@ -104,6 +104,7 @@ Suspend Nîşeyê jê bibe Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-ku/03-dialogs.xml b/AnkiDroid/src/main/res/values-ku/03-dialogs.xml index 80664e9ae6c7..778ae2931f5c 100644 --- a/AnkiDroid/src/main/res/values-ku/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ku/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ky/01-core.xml b/AnkiDroid/src/main/res/values-ky/01-core.xml index c81d73f3ec4d..7b620020eaf4 100644 --- a/AnkiDroid/src/main/res/values-ky/01-core.xml +++ b/AnkiDroid/src/main/res/values-ky/01-core.xml @@ -104,6 +104,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-ky/03-dialogs.xml b/AnkiDroid/src/main/res/values-ky/03-dialogs.xml index 43bdad1b692f..5dbe01d72fb0 100644 --- a/AnkiDroid/src/main/res/values-ky/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ky/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-lt/01-core.xml b/AnkiDroid/src/main/res/values-lt/01-core.xml index 934a7489b324..84f99f8b437b 100644 --- a/AnkiDroid/src/main/res/values-lt/01-core.xml +++ b/AnkiDroid/src/main/res/values-lt/01-core.xml @@ -110,6 +110,7 @@ Atidėti Ištrinti užrašą Pažymėti + Rename flags Pažymėti su vėliava Redaguoti žymes Ar tikrai norite ištrinti šį užrašą ir visas su juo susijusias korteles?\n%s diff --git a/AnkiDroid/src/main/res/values-lt/03-dialogs.xml b/AnkiDroid/src/main/res/values-lt/03-dialogs.xml index 3da29e029914..bf3642e560a6 100644 --- a/AnkiDroid/src/main/res/values-lt/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-lt/03-dialogs.xml @@ -274,4 +274,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-lv/01-core.xml b/AnkiDroid/src/main/res/values-lv/01-core.xml index 9cee85e8e0d4..1e9736047448 100644 --- a/AnkiDroid/src/main/res/values-lv/01-core.xml +++ b/AnkiDroid/src/main/res/values-lv/01-core.xml @@ -107,6 +107,7 @@ Izslēgt Dzēst piezīmi Karogs + Rename flags Uzliekt karogu Mainīt tegus Tiešām dzēst šo piezīmi un visas pievienotās kārtis?\n%s diff --git a/AnkiDroid/src/main/res/values-lv/03-dialogs.xml b/AnkiDroid/src/main/res/values-lv/03-dialogs.xml index c6f06f46a2d2..7166459b62b9 100644 --- a/AnkiDroid/src/main/res/values-lv/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-lv/03-dialogs.xml @@ -266,4 +266,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-mk/01-core.xml b/AnkiDroid/src/main/res/values-mk/01-core.xml index bd4dc7d1b302..47d98f9e835c 100644 --- a/AnkiDroid/src/main/res/values-mk/01-core.xml +++ b/AnkiDroid/src/main/res/values-mk/01-core.xml @@ -104,6 +104,7 @@ Суспендирај Бриши белешка Знаме + Rename flags Постави знаме на карта Edit tags Навистина избришете ја оваа белешка и сите нејзини картички?\n%s diff --git a/AnkiDroid/src/main/res/values-mk/03-dialogs.xml b/AnkiDroid/src/main/res/values-mk/03-dialogs.xml index 07c201640b45..10b365bc4550 100644 --- a/AnkiDroid/src/main/res/values-mk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mk/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ml/01-core.xml b/AnkiDroid/src/main/res/values-ml/01-core.xml index 70ff589ba061..6b56736457a0 100644 --- a/AnkiDroid/src/main/res/values-ml/01-core.xml +++ b/AnkiDroid/src/main/res/values-ml/01-core.xml @@ -104,6 +104,7 @@ സസ്പെൻഡ് ചെയ്യുക കുറിപ്പ് മായ്ക്കുക ഫ്ലാഗ് + Rename flags ഫ്ലാഗ് കാർഡ് ടാഗുകൾ എഡിറ്റുചെയ്യുക ഈ കുറിപ്പും അതിന്റെ എല്ലാ കാർഡുകളും ശരിക്കും ഇല്ലാതാക്കുക?\n%s diff --git a/AnkiDroid/src/main/res/values-ml/03-dialogs.xml b/AnkiDroid/src/main/res/values-ml/03-dialogs.xml index 5ae1f2af79b5..895fdf826fc9 100644 --- a/AnkiDroid/src/main/res/values-ml/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ml/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-mn/01-core.xml b/AnkiDroid/src/main/res/values-mn/01-core.xml index f7e50bb8c272..a4616556f5d0 100644 --- a/AnkiDroid/src/main/res/values-mn/01-core.xml +++ b/AnkiDroid/src/main/res/values-mn/01-core.xml @@ -104,6 +104,7 @@ Хасах Картын хэсгийг устгах Дарцаг + Rename flags Картыг дарцаглах Шошгийг солих Та үнэхээр энэ картыг, хэсгүүдтэй нь цуг устгамаар байна уу?\n%s diff --git a/AnkiDroid/src/main/res/values-mn/03-dialogs.xml b/AnkiDroid/src/main/res/values-mn/03-dialogs.xml index f2470c6ce0a9..f7477e9caaea 100644 --- a/AnkiDroid/src/main/res/values-mn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mn/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-mr/01-core.xml b/AnkiDroid/src/main/res/values-mr/01-core.xml index 1066a6fe3e19..c2cbb69792c2 100644 --- a/AnkiDroid/src/main/res/values-mr/01-core.xml +++ b/AnkiDroid/src/main/res/values-mr/01-core.xml @@ -104,6 +104,7 @@ निलंबित करा टीप हटवा झेंडा + Rename flags फ्लॅग कार्ड टॅग संपादित करा खरोखर ही टीप आणि त्याची सर्व कार्ड हटवायची?\n%s diff --git a/AnkiDroid/src/main/res/values-mr/03-dialogs.xml b/AnkiDroid/src/main/res/values-mr/03-dialogs.xml index 93e555f566bd..20fef009de7a 100644 --- a/AnkiDroid/src/main/res/values-mr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mr/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ms/01-core.xml b/AnkiDroid/src/main/res/values-ms/01-core.xml index a5d1d8bb38ed..08de71bcbfdb 100644 --- a/AnkiDroid/src/main/res/values-ms/01-core.xml +++ b/AnkiDroid/src/main/res/values-ms/01-core.xml @@ -101,6 +101,7 @@ Bekukan Padam nota Tanda + Rename flags Tanda kad Sunting tag Pasti padam nota dan semua kadnya?\n%s diff --git a/AnkiDroid/src/main/res/values-ms/03-dialogs.xml b/AnkiDroid/src/main/res/values-ms/03-dialogs.xml index d77fdd6042da..7acf4ace659e 100644 --- a/AnkiDroid/src/main/res/values-ms/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ms/03-dialogs.xml @@ -250,4 +250,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-my/01-core.xml b/AnkiDroid/src/main/res/values-my/01-core.xml index cbb2b92d7919..6501aeba54a2 100644 --- a/AnkiDroid/src/main/res/values-my/01-core.xml +++ b/AnkiDroid/src/main/res/values-my/01-core.xml @@ -105,6 +105,7 @@ ဆိုင်းငံ့ မှတ်စုကို ဖျက်ပစ်ပါ အလံ + Rename flags ကဒ်အလံ ကတ်ပြားပြင်ဆင် မှတ်စု နဲ့ ကတ်တွေဖြတ်မှာကျိန်းသေလား\n%s diff --git a/AnkiDroid/src/main/res/values-my/03-dialogs.xml b/AnkiDroid/src/main/res/values-my/03-dialogs.xml index 15b91c530f36..d55f88add175 100644 --- a/AnkiDroid/src/main/res/values-my/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-my/03-dialogs.xml @@ -250,4 +250,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-nl/01-core.xml b/AnkiDroid/src/main/res/values-nl/01-core.xml index 46e1986abe51..ec50c009e23e 100644 --- a/AnkiDroid/src/main/res/values-nl/01-core.xml +++ b/AnkiDroid/src/main/res/values-nl/01-core.xml @@ -104,6 +104,7 @@ Opschorten Notitie verwijderen Vlag + Rename flags Markeer kaart Tags bewerken Deze memo en al zijn kaarten verwijderen?\n%s diff --git a/AnkiDroid/src/main/res/values-nl/03-dialogs.xml b/AnkiDroid/src/main/res/values-nl/03-dialogs.xml index e5aa19200793..9f969b794547 100644 --- a/AnkiDroid/src/main/res/values-nl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-nl/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-nn/01-core.xml b/AnkiDroid/src/main/res/values-nn/01-core.xml index 350227e3ad6d..adad8752bf65 100644 --- a/AnkiDroid/src/main/res/values-nn/01-core.xml +++ b/AnkiDroid/src/main/res/values-nn/01-core.xml @@ -104,6 +104,7 @@ Suspender Slett notat Flagg + Rename flags Flagg kort Rediger tagger Slette dette notatet med alle kortene?\n%s diff --git a/AnkiDroid/src/main/res/values-nn/03-dialogs.xml b/AnkiDroid/src/main/res/values-nn/03-dialogs.xml index fdf1e3021453..fb291abc7cc6 100644 --- a/AnkiDroid/src/main/res/values-nn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-nn/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-no/01-core.xml b/AnkiDroid/src/main/res/values-no/01-core.xml index 488e3f9962ff..7f0edf45f1f1 100644 --- a/AnkiDroid/src/main/res/values-no/01-core.xml +++ b/AnkiDroid/src/main/res/values-no/01-core.xml @@ -104,6 +104,7 @@ Suspender Slett notat Flagg + Rename flags Flagg kortet Rediger tagger Slette dette notatet med alle kortene?\n%s diff --git a/AnkiDroid/src/main/res/values-no/03-dialogs.xml b/AnkiDroid/src/main/res/values-no/03-dialogs.xml index d4070917c157..2a85d3363251 100644 --- a/AnkiDroid/src/main/res/values-no/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-no/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-or/01-core.xml b/AnkiDroid/src/main/res/values-or/01-core.xml index da42a9801acc..8fd64557dd6e 100644 --- a/AnkiDroid/src/main/res/values-or/01-core.xml +++ b/AnkiDroid/src/main/res/values-or/01-core.xml @@ -104,6 +104,7 @@ ନିଲମ୍ବନ କରନ୍ତୁ ନୋଟ୍ ଵିଲୋପ କରିବା ପତାକା + Rename flags ପତ୍ରକୁ ଏକ ପତାକା ନ୍ୟସ୍ତ କରନ୍ତୁ ଟ୍ୟାଗ୍ ସମ୍ପାଦନା ଆପଣ ପ୍ରକୃତରେ ଏହି ନୋଟ୍ ଏଵଂ ଏହାର ସମସ୍ତ ପତ୍ର ଵିଲୋପ କରିବାକୁ ଚାହୁଁଛନ୍ତି କି?\n%s diff --git a/AnkiDroid/src/main/res/values-or/03-dialogs.xml b/AnkiDroid/src/main/res/values-or/03-dialogs.xml index e36a3156a075..e9ec65b1096a 100644 --- a/AnkiDroid/src/main/res/values-or/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-or/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-pa/01-core.xml b/AnkiDroid/src/main/res/values-pa/01-core.xml index 24f775cc6faa..cbd46ff7844c 100644 --- a/AnkiDroid/src/main/res/values-pa/01-core.xml +++ b/AnkiDroid/src/main/res/values-pa/01-core.xml @@ -104,6 +104,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-pa/03-dialogs.xml b/AnkiDroid/src/main/res/values-pa/03-dialogs.xml index 4843cb22d221..1893e8a40430 100644 --- a/AnkiDroid/src/main/res/values-pa/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pa/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-pl/01-core.xml b/AnkiDroid/src/main/res/values-pl/01-core.xml index 9bd6b423c256..2ed9a6dd8a9b 100644 --- a/AnkiDroid/src/main/res/values-pl/01-core.xml +++ b/AnkiDroid/src/main/res/values-pl/01-core.xml @@ -110,6 +110,7 @@ Zawieś Usuń notatkę Oflaguj + Rename flags Oflaguj kartę Edytuj etykiety Jesteś pewny, że chcesz usunąć tę notatkę i wszystkie jej karty?\n%s diff --git a/AnkiDroid/src/main/res/values-pl/03-dialogs.xml b/AnkiDroid/src/main/res/values-pl/03-dialogs.xml index fe8da3065b8e..7fc6fbfcb41d 100644 --- a/AnkiDroid/src/main/res/values-pl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pl/03-dialogs.xml @@ -274,4 +274,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml b/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml index 0be075ad1215..f17db378a236 100644 --- a/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml +++ b/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml @@ -104,6 +104,7 @@ Suspender Excluir nota Sinalização + Rename flags Sinalizar card Editar tags Deseja realmente excluir esta nota e todos seus cartões?\n%s diff --git a/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml b/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml index a9f22a956ea4..fb959a2ca461 100644 --- a/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml b/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml index de6ee149e54c..71de095016c4 100644 --- a/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml +++ b/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml @@ -104,6 +104,7 @@ Suspender Eliminar nota Sinalização + Rename flags Sinalizar ficha Editar etiquetas Deseja realmente eliminar esta nota e todas as suas fichas?\n%s diff --git a/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml b/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml index 9a4bc5c39ac6..336394714f74 100644 --- a/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml @@ -258,4 +258,6 @@ Abrir O sistema WebView está desatualizado. Alguns recursos não funcionarão corretamente. Atualize-o.\n\nVersão instalada: %1$d\nVersão mínima necessária: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ro/01-core.xml b/AnkiDroid/src/main/res/values-ro/01-core.xml index fc53be66e23d..8e7491e4c71c 100644 --- a/AnkiDroid/src/main/res/values-ro/01-core.xml +++ b/AnkiDroid/src/main/res/values-ro/01-core.xml @@ -107,6 +107,7 @@ Suspendă Ștergere notă Marcaj + Rename flags Marchează card Editează etichete Doriți sigur să ștergeți această notă și toate cardurile sale?\n%s diff --git a/AnkiDroid/src/main/res/values-ro/03-dialogs.xml b/AnkiDroid/src/main/res/values-ro/03-dialogs.xml index 1012cb1082ea..54494a7151d9 100644 --- a/AnkiDroid/src/main/res/values-ro/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ro/03-dialogs.xml @@ -266,4 +266,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ru/01-core.xml b/AnkiDroid/src/main/res/values-ru/01-core.xml index 2a72a1a9b0c9..8e24760971e7 100644 --- a/AnkiDroid/src/main/res/values-ru/01-core.xml +++ b/AnkiDroid/src/main/res/values-ru/01-core.xml @@ -110,6 +110,7 @@ Исключить Удалить запись Флажок + Rename flags Поставить флажок Редактировать метки Удалить эту запись и все связанные карточки?\n%s diff --git a/AnkiDroid/src/main/res/values-ru/03-dialogs.xml b/AnkiDroid/src/main/res/values-ru/03-dialogs.xml index 6f321ba1ccae..e1063a01bb72 100644 --- a/AnkiDroid/src/main/res/values-ru/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ru/03-dialogs.xml @@ -275,4 +275,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sat/01-core.xml b/AnkiDroid/src/main/res/values-sat/01-core.xml index 023caf3aed77..ebfe1722a940 100644 --- a/AnkiDroid/src/main/res/values-sat/01-core.xml +++ b/AnkiDroid/src/main/res/values-sat/01-core.xml @@ -104,6 +104,7 @@ ᱵᱚᱸᱫᱚᱭ ᱢᱮ ᱠᱷᱟᱴᱚ ᱵᱤᱪᱟᱹᱨ ᱜᱮᱫ ᱜᱤᱰᱤ ᱯᱚᱛᱠᱟ + Rename flags ᱠᱟᱰ ᱯᱚᱛᱠᱟᱭ ᱢᱮ ᱴᱮᱜᱥ ᱥᱟᱯᱲᱟᱣ ᱱᱚᱛᱴ ᱥᱟᱞᱟᱜ ᱛᱮ ᱡᱷᱚᱛᱚ ᱠᱟᱰ ᱨᱮᱭᱟᱜ ᱡᱤᱱᱥᱚ ᱠᱚ ᱜᱮᱫ ᱜᱤᱰᱤᱭᱟ ᱥᱮ?\n%s diff --git a/AnkiDroid/src/main/res/values-sat/03-dialogs.xml b/AnkiDroid/src/main/res/values-sat/03-dialogs.xml index c835d8064214..b7246cc045a5 100644 --- a/AnkiDroid/src/main/res/values-sat/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sat/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sc/01-core.xml b/AnkiDroid/src/main/res/values-sc/01-core.xml index bd235164c666..54543c3edafe 100644 --- a/AnkiDroid/src/main/res/values-sc/01-core.xml +++ b/AnkiDroid/src/main/res/values-sc/01-core.xml @@ -105,6 +105,7 @@ Suspende Iscantzella sa nota Bandera + Rename flags Marca sa carta cun una bandera Modìfica sas etichetas Boles a beru iscantzellare custa nota e totu sas cartas suas?\n diff --git a/AnkiDroid/src/main/res/values-sc/03-dialogs.xml b/AnkiDroid/src/main/res/values-sc/03-dialogs.xml index 2134871aa271..1858dba65581 100644 --- a/AnkiDroid/src/main/res/values-sc/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sc/03-dialogs.xml @@ -272,4 +272,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sk/01-core.xml b/AnkiDroid/src/main/res/values-sk/01-core.xml index 6759fd81e033..3f1cdf68fd21 100644 --- a/AnkiDroid/src/main/res/values-sk/01-core.xml +++ b/AnkiDroid/src/main/res/values-sk/01-core.xml @@ -110,6 +110,7 @@ Pozastaviť Vymazať poznámku Vlajočka + Rename flags Červená vlajočka Upraviť štítky Naozaj chcete odstrániť túto poznámku a všetky jej kartičky?\n%s diff --git a/AnkiDroid/src/main/res/values-sk/03-dialogs.xml b/AnkiDroid/src/main/res/values-sk/03-dialogs.xml index bff167a01072..e126314891d8 100644 --- a/AnkiDroid/src/main/res/values-sk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sk/03-dialogs.xml @@ -272,4 +272,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sl/01-core.xml b/AnkiDroid/src/main/res/values-sl/01-core.xml index 684e3face736..214f6f725835 100644 --- a/AnkiDroid/src/main/res/values-sl/01-core.xml +++ b/AnkiDroid/src/main/res/values-sl/01-core.xml @@ -110,6 +110,7 @@ Pridrži Izbriši zapisek Flag + Rename flags Flag card Edit tags Ali res želite izbrisati ta zapisek in vse vezane kartice?\n%s diff --git a/AnkiDroid/src/main/res/values-sl/03-dialogs.xml b/AnkiDroid/src/main/res/values-sl/03-dialogs.xml index 2cf9c93e032a..2331e0b1c284 100644 --- a/AnkiDroid/src/main/res/values-sl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sl/03-dialogs.xml @@ -274,4 +274,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sq/01-core.xml b/AnkiDroid/src/main/res/values-sq/01-core.xml index 506d5133ea6c..2316aaf8cc50 100644 --- a/AnkiDroid/src/main/res/values-sq/01-core.xml +++ b/AnkiDroid/src/main/res/values-sq/01-core.xml @@ -104,6 +104,7 @@ Pezulloni Fshij shënimin Flamurin + Rename flags Flamurin kartën Redakto etiketat Të fshihet vërtet ky shënim dhe të gjitha kartat e tij?\n%s diff --git a/AnkiDroid/src/main/res/values-sq/03-dialogs.xml b/AnkiDroid/src/main/res/values-sq/03-dialogs.xml index 46782b2ea83a..05adce91d63b 100644 --- a/AnkiDroid/src/main/res/values-sq/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sq/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sr/01-core.xml b/AnkiDroid/src/main/res/values-sr/01-core.xml index 3e8e2251f22a..f3c7fb232d0c 100644 --- a/AnkiDroid/src/main/res/values-sr/01-core.xml +++ b/AnkiDroid/src/main/res/values-sr/01-core.xml @@ -107,6 +107,7 @@ Suspend Избриши белешку Заставице + Rename flags Flag card Edit tags Да ли заисте желите да избришете белешку и све повезане карте?\n%s diff --git a/AnkiDroid/src/main/res/values-sr/03-dialogs.xml b/AnkiDroid/src/main/res/values-sr/03-dialogs.xml index 9917e1e6ce91..d3814f60101a 100644 --- a/AnkiDroid/src/main/res/values-sr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sr/03-dialogs.xml @@ -266,4 +266,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ss/01-core.xml b/AnkiDroid/src/main/res/values-ss/01-core.xml index a7c4ad222d5c..d9833f3293b9 100644 --- a/AnkiDroid/src/main/res/values-ss/01-core.xml +++ b/AnkiDroid/src/main/res/values-ss/01-core.xml @@ -104,6 +104,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-ss/03-dialogs.xml b/AnkiDroid/src/main/res/values-ss/03-dialogs.xml index f2470c6ce0a9..f7477e9caaea 100644 --- a/AnkiDroid/src/main/res/values-ss/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ss/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sv/01-core.xml b/AnkiDroid/src/main/res/values-sv/01-core.xml index d412633b29ee..21c9a7d9165c 100644 --- a/AnkiDroid/src/main/res/values-sv/01-core.xml +++ b/AnkiDroid/src/main/res/values-sv/01-core.xml @@ -104,6 +104,7 @@ Lås Ta bort not Flagga + Rename flags Flagga kort Redigera taggar Vill du verkligen ta bort den här noten och alla dess kort?\n%s diff --git a/AnkiDroid/src/main/res/values-sv/03-dialogs.xml b/AnkiDroid/src/main/res/values-sv/03-dialogs.xml index 0c576931e50e..08644981023c 100644 --- a/AnkiDroid/src/main/res/values-sv/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sv/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sw/01-core.xml b/AnkiDroid/src/main/res/values-sw/01-core.xml index a7c4ad222d5c..d9833f3293b9 100644 --- a/AnkiDroid/src/main/res/values-sw/01-core.xml +++ b/AnkiDroid/src/main/res/values-sw/01-core.xml @@ -104,6 +104,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-sw/03-dialogs.xml b/AnkiDroid/src/main/res/values-sw/03-dialogs.xml index f2470c6ce0a9..f7477e9caaea 100644 --- a/AnkiDroid/src/main/res/values-sw/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sw/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ta/01-core.xml b/AnkiDroid/src/main/res/values-ta/01-core.xml index cb8cbbf2bde1..cfeb70485c02 100644 --- a/AnkiDroid/src/main/res/values-ta/01-core.xml +++ b/AnkiDroid/src/main/res/values-ta/01-core.xml @@ -104,6 +104,7 @@ இடைநிறுத்த குறிப்பு நீக்கவும் கொடிகள் + Rename flags Flag card Tags-ஐ திருத்து உண்மையில் இந்த குறிப்பையும் அதன் அனைத்து அட்டைகளையும் நீக்கவா?\n%s diff --git a/AnkiDroid/src/main/res/values-ta/03-dialogs.xml b/AnkiDroid/src/main/res/values-ta/03-dialogs.xml index bda43a1ce1d4..a72bc28a8f82 100644 --- a/AnkiDroid/src/main/res/values-ta/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ta/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-te/01-core.xml b/AnkiDroid/src/main/res/values-te/01-core.xml index 881a37333afb..033a6ac93eef 100644 --- a/AnkiDroid/src/main/res/values-te/01-core.xml +++ b/AnkiDroid/src/main/res/values-te/01-core.xml @@ -104,6 +104,7 @@ సస్పెండ్ గమనికను తొలగించండి జెండా + Rename flags ఫ్లాగ్ కార్డ్ ట్యాగ్‌లను సవరించండి ఈ గమనికను మరియు దాని అన్ని కార్డ్లను నిజంగా తొలగించాలా?\n%s diff --git a/AnkiDroid/src/main/res/values-te/03-dialogs.xml b/AnkiDroid/src/main/res/values-te/03-dialogs.xml index a0dbe1bfd02c..319d3eb8c707 100644 --- a/AnkiDroid/src/main/res/values-te/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-te/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-tg/01-core.xml b/AnkiDroid/src/main/res/values-tg/01-core.xml index c1ddca0341cc..edbc8e78e659 100644 --- a/AnkiDroid/src/main/res/values-tg/01-core.xml +++ b/AnkiDroid/src/main/res/values-tg/01-core.xml @@ -104,6 +104,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-tg/03-dialogs.xml b/AnkiDroid/src/main/res/values-tg/03-dialogs.xml index 2b091d79c9e2..2a40920bc765 100644 --- a/AnkiDroid/src/main/res/values-tg/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tg/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-tgl/01-core.xml b/AnkiDroid/src/main/res/values-tgl/01-core.xml index b24c1dde5a08..74da823ad2f3 100644 --- a/AnkiDroid/src/main/res/values-tgl/01-core.xml +++ b/AnkiDroid/src/main/res/values-tgl/01-core.xml @@ -104,6 +104,7 @@ Suspendihin Burahin ang paalala Flag + Rename flags Flag card Edit tags Burahin tagala ang paalalang ito at lahat ng baraha nito?\n%s diff --git a/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml b/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml index 72a0b3cf8769..9c0f2592ef01 100644 --- a/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-th/01-core.xml b/AnkiDroid/src/main/res/values-th/01-core.xml index 26ec2c0cf727..9422e4dc07b6 100644 --- a/AnkiDroid/src/main/res/values-th/01-core.xml +++ b/AnkiDroid/src/main/res/values-th/01-core.xml @@ -101,6 +101,7 @@ ระงับ ลบโน้ต เครื่องหมาย + Rename flags เครื่องหมายการ์ด แก้ไขแท็ก คุณต้องการจะลบโน้ตนี้และการ์ดภายในทั้งหมดหรือไม่?\n%s diff --git a/AnkiDroid/src/main/res/values-th/03-dialogs.xml b/AnkiDroid/src/main/res/values-th/03-dialogs.xml index f1f35c733f05..0680d160e7ec 100644 --- a/AnkiDroid/src/main/res/values-th/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-th/03-dialogs.xml @@ -250,4 +250,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ti/01-core.xml b/AnkiDroid/src/main/res/values-ti/01-core.xml index 7699be916aaf..9a061665baf8 100644 --- a/AnkiDroid/src/main/res/values-ti/01-core.xml +++ b/AnkiDroid/src/main/res/values-ti/01-core.xml @@ -104,6 +104,7 @@ ስሓብ ጽሑፍ ደምስስ Flag + Rename flags Flag card Edit tags ናይባሓቂ ነዚ ጽሑፍ ከምኡ ውን ነዞም ካርድታትን ክትድምስስ ደሊኻ?\n%s diff --git a/AnkiDroid/src/main/res/values-ti/03-dialogs.xml b/AnkiDroid/src/main/res/values-ti/03-dialogs.xml index f2470c6ce0a9..f7477e9caaea 100644 --- a/AnkiDroid/src/main/res/values-ti/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ti/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-tn/01-core.xml b/AnkiDroid/src/main/res/values-tn/01-core.xml index a7c4ad222d5c..d9833f3293b9 100644 --- a/AnkiDroid/src/main/res/values-tn/01-core.xml +++ b/AnkiDroid/src/main/res/values-tn/01-core.xml @@ -104,6 +104,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-tn/03-dialogs.xml b/AnkiDroid/src/main/res/values-tn/03-dialogs.xml index f2470c6ce0a9..f7477e9caaea 100644 --- a/AnkiDroid/src/main/res/values-tn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tn/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-tr/01-core.xml b/AnkiDroid/src/main/res/values-tr/01-core.xml index 4e0ce1b27222..4943934b8643 100644 --- a/AnkiDroid/src/main/res/values-tr/01-core.xml +++ b/AnkiDroid/src/main/res/values-tr/01-core.xml @@ -104,6 +104,7 @@ Askıya Al Notu sil Bayrak + Rename flags Kartı bayrakla işaretle Etiketleri düzenle Bu not ve bütün kartları gerçekten silinsin mi?\n%s diff --git a/AnkiDroid/src/main/res/values-tr/03-dialogs.xml b/AnkiDroid/src/main/res/values-tr/03-dialogs.xml index ffb89753b71c..26f4b3e99bb1 100644 --- a/AnkiDroid/src/main/res/values-tr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tr/03-dialogs.xml @@ -258,4 +258,6 @@ Sistem WebView\'su güncel değil. Bazı özellikler doğru çalışmayacak. Lütfen güncelleyin.\n\nYüklü sürüm: %1$d\nGereken en düşük sürüm: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ts/01-core.xml b/AnkiDroid/src/main/res/values-ts/01-core.xml index a7c4ad222d5c..d9833f3293b9 100644 --- a/AnkiDroid/src/main/res/values-ts/01-core.xml +++ b/AnkiDroid/src/main/res/values-ts/01-core.xml @@ -104,6 +104,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-ts/03-dialogs.xml b/AnkiDroid/src/main/res/values-ts/03-dialogs.xml index f2470c6ce0a9..f7477e9caaea 100644 --- a/AnkiDroid/src/main/res/values-ts/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ts/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-tt/01-core.xml b/AnkiDroid/src/main/res/values-tt/01-core.xml index 5cf2174ad971..4c61286b5ae8 100644 --- a/AnkiDroid/src/main/res/values-tt/01-core.xml +++ b/AnkiDroid/src/main/res/values-tt/01-core.xml @@ -101,6 +101,7 @@ Искә алмау Язуны бетерү Төс + Rename flags Төс кую Тегларны үзгәртү Бу язуны һәм бөтен аның кәртләрен бетерергәме?\n%s diff --git a/AnkiDroid/src/main/res/values-tt/03-dialogs.xml b/AnkiDroid/src/main/res/values-tt/03-dialogs.xml index eb3823171c0b..4cfacc8ee4a4 100644 --- a/AnkiDroid/src/main/res/values-tt/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tt/03-dialogs.xml @@ -250,4 +250,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-uk/01-core.xml b/AnkiDroid/src/main/res/values-uk/01-core.xml index dc90483a424d..3f146b6159d7 100644 --- a/AnkiDroid/src/main/res/values-uk/01-core.xml +++ b/AnkiDroid/src/main/res/values-uk/01-core.xml @@ -110,6 +110,7 @@ Призупинити Видалити запис Прапорець + Rename flags Додати прапорець Редагувати примітки Дійсно видалити цей запис разом з усіма його картками?\n%s diff --git a/AnkiDroid/src/main/res/values-uk/03-dialogs.xml b/AnkiDroid/src/main/res/values-uk/03-dialogs.xml index 9b88fab45539..b7ed3f24a6d3 100644 --- a/AnkiDroid/src/main/res/values-uk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-uk/03-dialogs.xml @@ -274,4 +274,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ur/01-core.xml b/AnkiDroid/src/main/res/values-ur/01-core.xml index c82501d93068..f77c673136f5 100644 --- a/AnkiDroid/src/main/res/values-ur/01-core.xml +++ b/AnkiDroid/src/main/res/values-ur/01-core.xml @@ -104,6 +104,7 @@ معطل نوٹ حذف کریں فلیگ + Rename flags پرچم کارڈ کارڈز میں ترمیم کریں واقعی یہ نوٹ اور اس کے تمام کارڈز حذف کریں؟ \n%s diff --git a/AnkiDroid/src/main/res/values-ur/03-dialogs.xml b/AnkiDroid/src/main/res/values-ur/03-dialogs.xml index 48f4b6af0e5e..3a42063f91d9 100644 --- a/AnkiDroid/src/main/res/values-ur/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ur/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-uz/01-core.xml b/AnkiDroid/src/main/res/values-uz/01-core.xml index c358b9802da8..85a6ec665bb4 100644 --- a/AnkiDroid/src/main/res/values-uz/01-core.xml +++ b/AnkiDroid/src/main/res/values-uz/01-core.xml @@ -104,6 +104,7 @@ To\'xtatib turish Qaydni o\'chirish Bayroq + Rename flags Kartaga bayroq qo\'yish Teglarni tahrirlash Rostdan ham bu qayd va uning barcha kartalarini o\'chirish?\n%s diff --git a/AnkiDroid/src/main/res/values-uz/03-dialogs.xml b/AnkiDroid/src/main/res/values-uz/03-dialogs.xml index 73ff762ae652..0b5eaf531c33 100644 --- a/AnkiDroid/src/main/res/values-uz/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-uz/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ve/01-core.xml b/AnkiDroid/src/main/res/values-ve/01-core.xml index a7c4ad222d5c..d9833f3293b9 100644 --- a/AnkiDroid/src/main/res/values-ve/01-core.xml +++ b/AnkiDroid/src/main/res/values-ve/01-core.xml @@ -104,6 +104,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-ve/03-dialogs.xml b/AnkiDroid/src/main/res/values-ve/03-dialogs.xml index f2470c6ce0a9..f7477e9caaea 100644 --- a/AnkiDroid/src/main/res/values-ve/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ve/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-vi/01-core.xml b/AnkiDroid/src/main/res/values-vi/01-core.xml index 413334788559..fce3e46075b4 100644 --- a/AnkiDroid/src/main/res/values-vi/01-core.xml +++ b/AnkiDroid/src/main/res/values-vi/01-core.xml @@ -101,6 +101,7 @@ Tạm hoãn Xoá ghi chú Gắn cờ + Rename flags Gắn cờ thẻ Sửa tag Bạn thực sự muốn xoá ghi chú này cùng toàn bộ thẻ của nó?\n%s diff --git a/AnkiDroid/src/main/res/values-vi/03-dialogs.xml b/AnkiDroid/src/main/res/values-vi/03-dialogs.xml index 0414affcf26f..8bb1f2d8c29a 100644 --- a/AnkiDroid/src/main/res/values-vi/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-vi/03-dialogs.xml @@ -250,4 +250,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-wo/01-core.xml b/AnkiDroid/src/main/res/values-wo/01-core.xml index f7ae69e0b93e..05a12d6e13f3 100644 --- a/AnkiDroid/src/main/res/values-wo/01-core.xml +++ b/AnkiDroid/src/main/res/values-wo/01-core.xml @@ -101,6 +101,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-wo/03-dialogs.xml b/AnkiDroid/src/main/res/values-wo/03-dialogs.xml index f1f35c733f05..0680d160e7ec 100644 --- a/AnkiDroid/src/main/res/values-wo/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-wo/03-dialogs.xml @@ -250,4 +250,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-xh/01-core.xml b/AnkiDroid/src/main/res/values-xh/01-core.xml index a7c4ad222d5c..d9833f3293b9 100644 --- a/AnkiDroid/src/main/res/values-xh/01-core.xml +++ b/AnkiDroid/src/main/res/values-xh/01-core.xml @@ -104,6 +104,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-xh/03-dialogs.xml b/AnkiDroid/src/main/res/values-xh/03-dialogs.xml index f2470c6ce0a9..f7477e9caaea 100644 --- a/AnkiDroid/src/main/res/values-xh/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-xh/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-yue/01-core.xml b/AnkiDroid/src/main/res/values-yue/01-core.xml index ab8241c241a5..b5aa14e7bb57 100644 --- a/AnkiDroid/src/main/res/values-yue/01-core.xml +++ b/AnkiDroid/src/main/res/values-yue/01-core.xml @@ -101,6 +101,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-yue/03-dialogs.xml b/AnkiDroid/src/main/res/values-yue/03-dialogs.xml index c0d122875325..5c58754d77b8 100644 --- a/AnkiDroid/src/main/res/values-yue/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-yue/03-dialogs.xml @@ -250,4 +250,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml b/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml index fff36ec9e262..99909de3f56a 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml @@ -101,6 +101,7 @@ 暂停 删除笔记 旗标 + Rename flags 为卡片设置旗标 编辑标签​​​​​ 确定要删除此笔记及生成的卡片?\n%s diff --git a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml index a1042c33b8bd..64cd1ff0aabf 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml @@ -250,4 +250,6 @@ 打开 系统 WebView 已过时。有些功能将无法正常工作。请更新它。\n\n已安装版本: %1$d\n所需最低版本: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml b/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml index cf6d1ad82670..cf1f0018af19 100644 --- a/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml +++ b/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml @@ -102,6 +102,7 @@ 長久擱置 刪除筆記 標記 + Rename flags 標記卡片 編輯標籤 真的要刪除這個筆記跟它的卡片嗎?\n%s diff --git a/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml b/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml index 3541677286a3..29a0a44ef551 100644 --- a/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml @@ -250,4 +250,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-zu/01-core.xml b/AnkiDroid/src/main/res/values-zu/01-core.xml index a7c4ad222d5c..d9833f3293b9 100644 --- a/AnkiDroid/src/main/res/values-zu/01-core.xml +++ b/AnkiDroid/src/main/res/values-zu/01-core.xml @@ -104,6 +104,7 @@ Suspend Delete note Flag + Rename flags Flag card Edit tags Really delete this note and all its cards?\n%s diff --git a/AnkiDroid/src/main/res/values-zu/03-dialogs.xml b/AnkiDroid/src/main/res/values-zu/03-dialogs.xml index f2470c6ce0a9..f7477e9caaea 100644 --- a/AnkiDroid/src/main/res/values-zu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zu/03-dialogs.xml @@ -258,4 +258,6 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d + + Confirm all changes before saving From 13189e0ac49ecccd02406a298aaea4b6e394fa34 Mon Sep 17 00:00:00 2001 From: SanjaySargam Date: Tue, 11 Jun 2024 10:37:49 +0530 Subject: [PATCH 088/138] remove back button on large screen only This bug existed for a long time which was unnoticed. Back button is useful on small screen when the fragment appears on a separate screen, and is not useful when the fragment appears near the deck-picker, where there is nowhere to go back to, so we could remove the button --- .../src/main/java/com/ichi2/anki/StudyOptionsFragment.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/StudyOptionsFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/StudyOptionsFragment.kt index 0420a859afee..f614d8c4b7fe 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/StudyOptionsFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/StudyOptionsFragment.kt @@ -358,7 +358,10 @@ class StudyOptionsFragment : Fragment(), ChangeManager.Subscriber, Toolbar.OnMen menu.findItem(R.id.action_undo).title = col?.undoLabel() } // Set the back button listener - if (!fragmented) { + if (fragmented) { + // when the fragment is attached to deck picker on large screen, the "back" button had no purpose, so it should be removed + toolbar!!.navigationIcon = null + } else { val icon = AppCompatResources.getDrawable(requireContext(), R.drawable.ic_arrow_back_white) icon!!.isAutoMirrored = true toolbar!!.navigationIcon = icon From b2f24d95de46fa16a032cb737a6acab6a39fdefa Mon Sep 17 00:00:00 2001 From: Shruti Gitte Date: Mon, 17 Jun 2024 01:42:50 +0530 Subject: [PATCH 089/138] fix: use android import for crash report dialog --- .../com/ichi2/anki/analytics/AnkiDroidCrashReportDialog.kt | 2 +- .../java/com/ichi2/anki/lint/rules/AvoidAlertDialogUsage.kt | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/analytics/AnkiDroidCrashReportDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/analytics/AnkiDroidCrashReportDialog.kt index ffd99d0c6f19..0b4199fa8460 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/analytics/AnkiDroidCrashReportDialog.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/analytics/AnkiDroidCrashReportDialog.kt @@ -17,12 +17,12 @@ package com.ichi2.anki.analytics import android.annotation.SuppressLint +import android.app.AlertDialog import android.content.DialogInterface import android.os.Bundle import android.view.View import android.widget.CheckBox import android.widget.EditText -import androidx.appcompat.app.AlertDialog import androidx.core.content.edit import com.ichi2.anki.CrashReportService import com.ichi2.anki.R diff --git a/lint-rules/src/main/java/com/ichi2/anki/lint/rules/AvoidAlertDialogUsage.kt b/lint-rules/src/main/java/com/ichi2/anki/lint/rules/AvoidAlertDialogUsage.kt index 48fa2e45a84c..bc52c0e800cf 100644 --- a/lint-rules/src/main/java/com/ichi2/anki/lint/rules/AvoidAlertDialogUsage.kt +++ b/lint-rules/src/main/java/com/ichi2/anki/lint/rules/AvoidAlertDialogUsage.kt @@ -21,6 +21,7 @@ import com.android.tools.lint.client.api.UElementHandler import com.android.tools.lint.detector.api.* import com.google.common.annotations.VisibleForTesting import com.ichi2.anki.lint.utils.Constants +import com.ichi2.anki.lint.utils.LintUtils import org.jetbrains.uast.UElement import org.jetbrains.uast.UImportStatement @@ -57,7 +58,9 @@ class AvoidAlertDialogUsage : Detector(), SourceCodeScanner { return object : UElementHandler() { override fun visitImportStatement(node: UImportStatement) { val importReference = node.asSourceString() - if (importReference.contains("android.app.AlertDialog")) { + if (importReference.contains("android.app.AlertDialog") && + !LintUtils.isAnAllowedClass(context.uastFile!!.classes, "AnkiDroidCrashReportDialog") + ) { context.report( ISSUE, node, From cbb64a86b6bbc2072f2c36d51f900feedff3b549 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Tue, 18 Jun 2024 15:06:28 +0100 Subject: [PATCH 090/138] test(card-browser-view-model): increase coverage (#16562) * test(card-browser-view-model): delete * test(card-browser-view-model): select all * test(card-browser-view-model): saved search * test(card-browser-view-model): 'marked' search * test(card-browser-view-model): 'suspended' search * test(card-browser-view-model): preview intent --- .../anki/browser/CardBrowserViewModel.kt | 23 ++- .../anki/browser/CardBrowserViewModelTest.kt | 156 +++++++++++++++++- 2 files changed, 176 insertions(+), 3 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index 1e574adc0836..91114de5ecdd 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -18,6 +18,7 @@ package com.ichi2.anki.browser import android.os.Parcel import android.os.Parcelable +import androidx.annotation.CheckResult import androidx.core.content.edit import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -364,8 +365,14 @@ class CardBrowserViewModel( * @return the number of deleted notes */ suspend fun deleteSelectedNotes(): Int { + // PERF: use `undoableOp(this)` & notify CardBrowser of changes + // this does a double search val cardIds = queryAllSelectedCardIds() return undoableOp { removeNotes(cids = cardIds) }.count + .also { + endMultiSelectMode() + refreshSearch() + } } fun setCardsOrNotes(newValue: CardsOrNotes) = viewModelScope.launch { @@ -592,6 +599,7 @@ class CardBrowserViewModel( } } + @CheckResult suspend fun saveSearch(searchName: String, searchTerms: String): SaveSearchResult { Timber.d("saving user search") var alreadyExists = false @@ -614,9 +622,18 @@ class CardBrowserViewModel( launchSearchForCards(filterQuery) } - suspend fun searchForMarkedNotes() = setFilterQuery("tag:marked") + suspend fun searchForMarkedNotes() { + // only intended to be used if the user has no selection + if (hasSelectedAnyRows()) return + setFilterQuery("tag:marked") + } + + suspend fun searchForSuspendedCards() { + // only intended to be used if the user has no selection + if (hasSelectedAnyRows()) return + setFilterQuery("is:suspended") + } - suspend fun searchForSuspendedCards() = setFilterQuery("is:suspended") suspend fun setFlagFilter(flag: Flag) { Timber.i("filtering to flag: %s", flag) val flagSearchTerm = "flag:${flag.code}" @@ -741,6 +758,8 @@ class CardBrowserViewModel( return searchJob!! } + private suspend fun refreshSearch() = launchSearchForCards()?.join() + private suspend fun clearCardsList() { cards.reset() flowOfCardsUpdated.emit(Unit) diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index 099c370f0a42..5ae2ae7e797c 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -33,6 +33,7 @@ import com.ichi2.anki.model.CardsOrNotes import com.ichi2.anki.model.SortType.EASE import com.ichi2.anki.model.SortType.NO_SORTING import com.ichi2.anki.model.SortType.SORT_FIELD +import com.ichi2.anki.servicelayer.NoteService import com.ichi2.anki.setFlagFilterSync import com.ichi2.anki.utils.ext.ifNotZero import com.ichi2.libanki.Consts.QUEUE_TYPE_MANUALLY_BURIED @@ -68,7 +69,9 @@ import kotlin.test.assertNull class CardBrowserViewModelTest : JvmTest() { @Test fun `delete search history - Issue 14989`() = runViewModelTest { - saveSearch("hello", "aa") + saveSearch("hello", "aa").also { result -> + assertThat(result, equalTo(SaveSearchResult.SUCCESS)) + } savedSearches().also { searches -> assertThat("filters after saving", searches.size, equalTo(1)) assertThat("filters after saving", searches["hello"], equalTo("aa")) @@ -77,6 +80,16 @@ class CardBrowserViewModelTest : JvmTest() { assertThat("filters should be empty after removing", savedSearches().size, equalTo(0)) } + @Test + fun `saving search with same name fails`() = runViewModelTest { + saveSearch("hello", "aa").also { result -> + assertThat("saving a new search succeeds", result, equalTo(SaveSearchResult.SUCCESS)) + } + saveSearch("hello", "bb").also { result -> + assertThat("saving with same name fails", result, equalTo(SaveSearchResult.ALREADY_EXISTS)) + } + } + @Test fun `change deck in notes mode 15444`() = runViewModelTest { val newDeck = addDeck("World") @@ -289,6 +302,15 @@ class CardBrowserViewModelTest : JvmTest() { } } + @Test + fun `executing select all twice does nothing`() = runViewModelTest(notes = 2) { + assertThat(selectedRowCount(), equalTo(0)) + selectAll() + assertThat(selectedRowCount(), equalTo(2)) + selectAll() + assertThat(selectedRowCount(), equalTo(2)) + } + @Test fun `changing column index 1`() = runViewModelTest { flowOfColumnIndex1.test { @@ -497,6 +519,138 @@ class CardBrowserViewModelTest : JvmTest() { assertThat(ids.single(), equalTo(cards[0].card.nid)) } + @Test + fun `cards - delete one`() = runViewModelTest(notes = 2) { + assertThat("initial card count", col.cardCount(), equalTo(2)) + selectRowsWithPositions(0) + + ensureOpsExecuted(1) { + deleteSelectedNotes() + } + + assertThat("1 card deleted", col.cardCount(), equalTo(1)) + assertThat("no selection after", selectedRowCount(), equalTo(0)) + assertThat("one row removed", rowCount, equalTo(1)) + } + + @Test + fun `notes - delete one`() = runViewModelNotesTest(notes = 2) { + assertThat("initial card count", col.cardCount(), equalTo(4)) + selectRowsWithPositions(0) + + ensureOpsExecuted(1) { + deleteSelectedNotes() + } + + assertThat("1 note deleted - 2 cards deleted", col.cardCount(), equalTo(2)) + assertThat("no selection after", selectedRowCount(), equalTo(0)) + assertThat("one row removed", rowCount, equalTo(1)) + } + + @Test + fun `notes - search for marked`() = runTest { + addNoteUsingBasicAndReversedModel("hello", "world").also { note -> + NoteService.toggleMark(note) + } + addNoteUsingBasicAndReversedModel("hello2", "world") + + runViewModelNotesTest { + searchForMarkedNotes() + waitForSearchResults() + assertThat("A marked note is found", rowCount, equalTo(1)) + } + } + + @Test + fun `cards - search for marked`() = runTest { + addNoteUsingBasicAndReversedModel("hello", "world").also { note -> + NoteService.toggleMark(note) + } + addNoteUsingBasicAndReversedModel("hello2", "world") + + runViewModelTest { + searchForMarkedNotes() + waitForSearchResults() + assertThat("both cards of a marked note are found", rowCount, equalTo(2)) + } + } + + @Test + fun `notes - search for suspended`() = runTest { + addNoteUsingBasicAndReversedModel("hello", "world").also { note -> + col.sched.suspendCards(listOf(note.cardIds(col).first())) + } + addNoteUsingBasicAndReversedModel("hello2", "world") + + runViewModelNotesTest { + searchForSuspendedCards() + waitForSearchResults() + assertThat("A suspended card is found for the note", rowCount, equalTo(1)) + } + } + + @Test + fun `cards - search for suspended`() = runTest { + addNoteUsingBasicAndReversedModel("hello", "world").also { note -> + col.sched.suspendCards(listOf(note.cardIds(col).first())) + } + + runViewModelTest { + searchForSuspendedCards() + waitForSearchResults() + assertThat("one suspended cards of a note is found", rowCount, equalTo(1)) + } + } + + @Test + fun `notes - preview intent`() = runViewModelNotesTest(notes = 5) { + assertThat("note count", col.noteCount(), equalTo(5)) + assertThat("card count", col.cardCount(), equalTo(10)) + val data = queryPreviewIntentData() + assertThat(data.currentIndex, equalTo(0)) + + data.previewerIdsFile.getCardIds().also { actualCardIds -> + assertThat("previewing a note previews cards", actualCardIds, hasSize(5)) + + val firstCardIds = col.findCards("") + .filter { col.getCard(it).ord == 0 } + + assertThat("first card ids", firstCardIds, hasSize(5)) + + // TODO: this behaviour is unconfirmed in Anki Desktop + assertThat( + "previewing first card in each note", + actualCardIds.toLongArray(), + equalTo(firstCardIds.toLongArray()) + ) + } + } + + @Test + fun `cards - preview intent - no selection`() = runViewModelTest(notes = 2) { + val data = queryPreviewIntentData() + assertThat(data.currentIndex, equalTo(0)) + assertThat(data.previewerIdsFile.getCardIds(), hasSize(2)) + } + + @Test + fun `cards - preview intent - selection`() = runViewModelTest(notes = 2) { + selectRowsWithPositions(0).also { + val data = queryPreviewIntentData() + assertThat(data.currentIndex, equalTo(0)) + assertThat(data.previewerIdsFile.getCardIds(), hasSize(2)) + } + + selectNone() + + // ensure currentIndex changes + selectRowsWithPositions(1).also { + val data = queryPreviewIntentData() + assertThat(data.currentIndex, equalTo(1)) + assertThat(data.previewerIdsFile.getCardIds(), hasSize(2)) + } + } + private fun runViewModelNotesTest( notes: Int = 0, manualInit: Boolean = true, From 14813c15532eda25d5fdcc8dd03e2e957caf689b Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+BrayanDSO@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:35:42 -0300 Subject: [PATCH 091/138] chore: update to anki 24.06.2 and adopt SvelteKit (#16449) * 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 --- .../java/com/ichi2/anki/PagesTest.kt | 1 - .../com/ichi2/anki/AbstractFlashcardViewer.kt | 2 - .../java/com/ichi2/anki/BackendImporting.kt | 13 +++-- .../main/java/com/ichi2/anki/CardBrowser.kt | 1 - .../src/main/java/com/ichi2/anki/Reviewer.kt | 2 +- .../anki/pages/AnkiPackageImporterFragment.kt | 23 ++------ .../java/com/ichi2/anki/pages/CardInfo.kt | 57 ------------------- .../ichi2/anki/pages/CardInfoDestination.kt | 28 +++++++++ .../java/com/ichi2/anki/pages/CongratsPage.kt | 5 +- .../java/com/ichi2/anki/pages/CsvImporter.kt | 22 ++----- .../java/com/ichi2/anki/pages/DeckOptions.kt | 41 +------------ .../com/ichi2/anki/pages/ImageOcclusion.kt | 57 +++++++++++-------- .../java/com/ichi2/anki/pages/PageFragment.kt | 34 ++++++++--- .../com/ichi2/anki/pages/PageWebViewClient.kt | 50 +++++++++++++--- .../java/com/ichi2/anki/pages/Statistics.kt | 7 +-- .../anki/previewer/CardViewerFragment.kt | 7 --- .../anki/previewer/CardViewerViewModel.kt | 21 ++++++- .../anki/previewer/PreviewerViewModel.kt | 2 + .../previewer/TemplatePreviewerViewModel.kt | 2 + .../anki/scheduling/ForgetCardsViewModel.kt | 3 +- .../ui/windows/reviewer/ReviewerViewModel.kt | 13 ++--- .../com/ichi2/libanki/BackendImportExport.kt | 6 ++ gradle/libs.versions.toml | 2 +- 23 files changed, 185 insertions(+), 214 deletions(-) delete mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/pages/CardInfo.kt create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/pages/CardInfoDestination.kt diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/PagesTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/PagesTest.kt index d8246f753734..8471861b40b3 100644 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/PagesTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/PagesTest.kt @@ -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 diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt b/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt index e726348cfe29..9dfad3b7c467 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt @@ -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( diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/BackendImporting.kt b/AnkiDroid/src/main/java/com/ichi2/anki/BackendImporting.kt index 8b732bde317c..e512e1ada1a6 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/BackendImporting.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/BackendImporting.kt @@ -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() } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt index 5657a284f2ff..138b9de3b8e6 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt @@ -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 diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt b/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt index c678209e1078..8d0d1c16290c 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt @@ -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.* @@ -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)) { diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/pages/AnkiPackageImporterFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/pages/AnkiPackageImporterFragment.kt index ddf84d01d260..33fbb4a1482f 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/pages/AnkiPackageImporterFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/pages/AnkiPackageImporterFragment.kt @@ -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 @@ -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() { /** @@ -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) } } @@ -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) } } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/pages/CardInfo.kt b/AnkiDroid/src/main/java/com/ichi2/anki/pages/CardInfo.kt deleted file mode 100644 index 05013eb95a0c..000000000000 --- a/AnkiDroid/src/main/java/com/ichi2/anki/pages/CardInfo.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2022 Brayan Oliveira - * - * 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 . - */ -package com.ichi2.anki.pages - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.webkit.WebView -import androidx.core.os.bundleOf -import com.ichi2.anki.R -import com.ichi2.anki.SingleFragmentActivity -import com.ichi2.libanki.CardId - -class CardInfo : PageFragment() { - override val title: String - get() = resources.getString(R.string.card_info_title) - - override val pageName = "card-info" - - override fun onCreateWebViewClient(savedInstanceState: Bundle?): PageWebViewClient { - val cardId = arguments?.getLong(ARG_CARD_ID) - ?: throw Exception("missing card ID argument") - return CardInfoWebClient(cardId) - } - - class CardInfoWebClient(val cardId: Long) : PageWebViewClient() { - override fun onPageFinished(view: WebView?, url: String?) { - // from upstream: https://github.com/ankitects/anki/blob/678c354fed4d98c0a8ef84fb7981ee085bd744a7/qt/aqt/browser/card_info.py#L66-L72 - view!!.evaluateJavascript("anki.cardInfoPromise = anki.setupCardInfo(document.body);", null) - view.evaluateJavascript("anki.cardInfoPromise.then((c) => c.updateStats($cardId));") { - super.onPageFinished(view, url) - } - } - } - - companion object { - private const val ARG_CARD_ID = "cardId" - - fun CardInfoDestination.toIntent(context: Context): Intent = - SingleFragmentActivity.getIntent(context, CardInfo::class, bundleOf(ARG_CARD_ID to cardId)) - } -} - -data class CardInfoDestination(val cardId: CardId) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/pages/CardInfoDestination.kt b/AnkiDroid/src/main/java/com/ichi2/anki/pages/CardInfoDestination.kt new file mode 100644 index 000000000000..864104af4817 --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/anki/pages/CardInfoDestination.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 Brayan Oliveira + * + * 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 . + */ +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) + } +} diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/pages/CongratsPage.kt b/AnkiDroid/src/main/java/com/ichi2/anki/pages/CongratsPage.kt index 0e1bf95b3945..275f401b374b 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/pages/CongratsPage.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/pages/CongratsPage.kt @@ -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 @@ -61,8 +60,6 @@ class CongratsPage : PageFragment(), CustomStudyDialog.CustomStudyListener, ChangeManager.Subscriber { - override val title: String = "" - override val pageName = "congrats" private val viewModel by viewModels() @@ -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 = diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/pages/CsvImporter.kt b/AnkiDroid/src/main/java/com/ichi2/anki/pages/CsvImporter.kt index 30b9ec656c71..b447d063ab6d 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/pages/CsvImporter.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/pages/CsvImporter.kt @@ -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 @@ -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() { /** @@ -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) } } @@ -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) } } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/pages/DeckOptions.kt b/AnkiDroid/src/main/java/com/ichi2/anki/pages/DeckOptions.kt index 57deb785ccf6..8b3e73c031b9 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/pages/DeckOptions.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/pages/DeckOptions.kt @@ -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 @@ -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) { @@ -65,12 +58,9 @@ 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() @@ -78,35 +68,10 @@ class DeckOptions : PageFragment() { } } - @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) } } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/pages/ImageOcclusion.kt b/AnkiDroid/src/main/java/com/ichi2/anki/pages/ImageOcclusion.kt index 0ee648e2b3f6..5a92bfc4e9b6 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/pages/ImageOcclusion.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/pages/ImageOcclusion.kt @@ -23,7 +23,6 @@ import android.webkit.WebView import androidx.activity.addCallback import androidx.core.os.bundleOf import com.google.android.material.appbar.MaterialToolbar -import com.ichi2.anki.CollectionManager.TR import com.ichi2.anki.R import com.ichi2.anki.SingleFragmentActivity import com.ichi2.anki.dialogs.DiscardChangesDialog @@ -32,10 +31,6 @@ import timber.log.Timber class ImageOcclusion : PageFragment(R.layout.image_occlusion) { - override val title: String - get() = TR.notetypesImageOcclusionName() - override val pageName = "image-occlusion" - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -50,31 +45,33 @@ class ImageOcclusion : PageFragment(R.layout.image_occlusion) { view.findViewById(R.id.toolbar).setOnMenuItemClickListener { if (it.itemId == R.id.action_save) { Timber.i("save item selected") - webView.evaluateJavascript("anki.imageOcclusion.addNote()", null) + webView.evaluateJavascript("anki.imageOcclusion.save()", null) } return@setOnMenuItemClickListener true } } override fun onCreateWebViewClient(savedInstanceState: Bundle?): PageWebViewClient { - 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 "" - return ImageOcclusionWebViewClient(kind, id, path) - } - - 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);") { + return object : PageWebViewClient() { + override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) + + val kind = requireArguments().getString(ARG_KEY_KIND) + val noteOrNotetypeId = requireArguments().getLong(ARG_KEY_ID) + val imagePath = requireArguments().getString(ARG_KEY_PATH) + + val options = JSONObject() + options.put("kind", kind) + if (kind == "add") { + options.put("imagePath", imagePath) + options.put("notetypeId", noteOrNotetypeId) + } else { + options.put("noteId", noteOrNotetypeId) + } + + view?.evaluateJavascript("globalThis.anki.imageOcclusion.mode = $options") { + super.onPageFinished(view, url) + } } } } @@ -82,10 +79,20 @@ class ImageOcclusion : PageFragment(R.layout.image_occlusion) { companion object { private const val ARG_KEY_KIND = "kind" private const val ARG_KEY_ID = "id" - private const val ARG_KEY_PATH = "path" + private const val ARG_KEY_PATH = "imagePath" fun getIntent(context: Context, kind: String, noteOrNotetypeId: Long, imagePath: String?): Intent { - val arguments = bundleOf(ARG_KEY_KIND to kind, ARG_KEY_ID to noteOrNotetypeId, ARG_KEY_PATH to imagePath) + val suffix = if (kind == "edit") { + "/$noteOrNotetypeId" + } else { + imagePath + } + val arguments = bundleOf( + ARG_KEY_KIND to kind, + ARG_KEY_ID to noteOrNotetypeId, + ARG_KEY_PATH to imagePath, + PATH_ARG_KEY to "image-occlusion$suffix" + ) return SingleFragmentActivity.getIntent(context, ImageOcclusion::class, arguments) } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/pages/PageFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/pages/PageFragment.kt index 4d58ad5f412e..c545a2890d9b 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/pages/PageFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/pages/PageFragment.kt @@ -15,29 +15,32 @@ */ package com.ichi2.anki.pages +import android.content.Context +import android.content.Intent +import android.net.Uri import android.os.Bundle import android.view.View import android.webkit.WebView import android.webkit.WebViewClient import androidx.annotation.CallSuper import androidx.annotation.LayoutRes +import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import com.google.android.material.appbar.MaterialToolbar import com.ichi2.anki.R +import com.ichi2.anki.SingleFragmentActivity import com.ichi2.themes.Themes import timber.log.Timber +import kotlin.reflect.KClass /** * Base class for displaying Anki HTML pages */ @Suppress("LeakingThis") -abstract class PageFragment(@LayoutRes contentLayoutId: Int = R.layout.page_fragment) : +open class PageFragment(@LayoutRes contentLayoutId: Int = R.layout.page_fragment) : Fragment(contentLayoutId), PostRequestHandler { - abstract val title: String - abstract val pageName: String - lateinit var webView: WebView private val server = AnkiServer(this).also { it.start() } @@ -62,14 +65,20 @@ abstract class PageFragment(@LayoutRes contentLayoutId: Int = R.layout.page_frag webViewClient = onCreateWebViewClient(savedInstanceState) webChromeClient = PageChromeClient() } - val nightMode = if (Themes.currentTheme.isNightMode) "#night" else "" - val url = server.baseUrl() + "backend/web/$pageName.html$nightMode" + val arguments = requireArguments() + val path = requireNotNull(arguments.getString(PATH_ARG_KEY)) { "'$PATH_ARG_KEY' missing" } + val title = arguments.getString(TITLE_ARG_KEY) + + val nightMode = if (Themes.currentTheme.isNightMode) "#night" else "" + val url = Uri.parse("${server.baseUrl()}$path$nightMode") Timber.i("Loading $url") - webView.loadUrl(url) + webView.loadUrl(url.toString()) view.findViewById(R.id.toolbar).apply { - title = this@PageFragment.title + if (title != null) { + setTitle(title) + } setNavigationOnClickListener { requireActivity().onBackPressedDispatcher.onBackPressed() } @@ -86,4 +95,13 @@ abstract class PageFragment(@LayoutRes contentLayoutId: Int = R.layout.page_frag ?: handleCollectionPostRequest(methodName, bytes) ?: throw IllegalArgumentException("unhandled method: $methodName") } + companion object { + const val PATH_ARG_KEY = "path" + const val TITLE_ARG_KEY = "title" + + fun getIntent(context: Context, path: String, title: String? = null, clazz: KClass = PageFragment::class): Intent { + val arguments = bundleOf(PATH_ARG_KEY to path, TITLE_ARG_KEY to title) + return SingleFragmentActivity.getIntent(context, clazz, arguments) + } + } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/pages/PageWebViewClient.kt b/AnkiDroid/src/main/java/com/ichi2/anki/pages/PageWebViewClient.kt index f2825233fb6a..db825f8ffbf4 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/pages/PageWebViewClient.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/pages/PageWebViewClient.kt @@ -24,9 +24,10 @@ import android.webkit.WebViewClient import androidx.core.view.isVisible import com.google.android.material.color.MaterialColors import com.ichi2.anki.OnPageFinishedCallback -import com.ichi2.utils.AssetHelper +import com.ichi2.utils.AssetHelper.guessMimeType import com.ichi2.utils.toRGBHex import timber.log.Timber +import java.io.ByteArrayInputStream import java.io.IOException /** @@ -44,16 +45,31 @@ open class PageWebViewClient : WebViewClient() { request: WebResourceRequest ): WebResourceResponse? { val path = request.url.path - if (request.method == "GET" && path?.startsWith("/backend/web") == true) { - try { - val mime = AssetHelper.guessMimeType(path) - val inputStream = view.context.assets.open(path.substring(1)) - return WebResourceResponse(mime, null, inputStream) - } catch (_: IOException) { - Timber.w("%s not found", path) + if (request.method != "GET" || path == null) return null + if (path == "/favicon.png") { + return WebResourceResponse("image/x-icon", null, ByteArrayInputStream(byteArrayOf())) + } + + val assetPath = if (path.startsWith("/_app/")) { + "backend/sveltekit/app/${path.substring(6)}" + } else if (isSvelteKitPage(path.substring(1))) { + "backend/sveltekit/index.html" + } else { + return null + } + + try { + val mimeType = guessMimeType(assetPath) + val inputStream = view.context.assets.open(assetPath) + val response = WebResourceResponse(mimeType, null, inputStream) + if ("immutable" in path) { + response.responseHeaders = mapOf("Cache-Control" to "max-age=31536000") } + return response + } catch (_: IOException) { + Timber.w("Not found %s", assetPath) } - return super.shouldInterceptRequest(view, request) + return null } override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { @@ -110,6 +126,22 @@ open class PageWebViewClient : WebViewClient() { } } +fun isSvelteKitPage(path: String): Boolean { + val pageName = path.substringBefore("/") + return when (pageName) { + "graphs", + "congrats", + "card-info", + "change-notetype", + "deck-options", + "import-anki-package", + "import-csv", + "import-page", + "image-occlusion" -> true + else -> false + } +} + fun WebView.evaluateAfterDOMContentLoaded(script: String, resultCallback: ValueCallback? = null) { evaluateJavascript( """ diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/pages/Statistics.kt b/AnkiDroid/src/main/java/com/ichi2/anki/pages/Statistics.kt index cab2c39026bb..6b921ad33c53 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/pages/Statistics.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/pages/Statistics.kt @@ -26,15 +26,10 @@ import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.MaterialToolbar import com.ichi2.anki.CollectionManager import com.ichi2.anki.R -import com.ichi2.anki.SingleFragmentActivity import com.ichi2.anki.utils.getTimestamp import com.ichi2.libanki.utils.TimeManager class Statistics : PageFragment(R.layout.statistics) { - override val title: String - get() = resources.getString(R.string.statistics) - - override val pageName = "graphs" override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -72,7 +67,7 @@ class Statistics : PageFragment(R.layout.statistics) { companion object { fun getIntent(context: Context): Intent { - return SingleFragmentActivity.getIntent(context, Statistics::class) + return getIntent(context, "graphs", context.getString(R.string.statistics), Statistics::class) } } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/CardViewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/CardViewerFragment.kt index 58bee5db325d..c69ce62c9334 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/CardViewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/CardViewerFragment.kt @@ -16,7 +16,6 @@ package com.ichi2.anki.previewer import android.content.Intent -import android.graphics.Bitmap import android.net.Uri import android.os.Bundle import android.view.View @@ -134,12 +133,6 @@ abstract class CardViewerFragment(@LayoutRes layout: Int) : Fragment(layout) { return resourceHandler.shouldInterceptRequest(request) } - override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { - super.onPageStarted(view, url, favicon) - // TODO remove this after the backend is upgraded to v0.1.39 - view?.evaluateJavascript("globalThis.ankidroid = globalThis.ankidroid || {}; ankidroid.postBaseUrl = ``", null) - } - override fun onPageFinished(view: WebView?, url: String?) { viewModel.onPageFinished(isAfterRecreation = savedInstanceState != null) } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/CardViewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/CardViewerViewModel.kt index f2f3e2fc355b..e4a2c7038878 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/CardViewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/CardViewerViewModel.kt @@ -30,6 +30,7 @@ import com.ichi2.anki.cardviewer.SoundErrorBehavior import com.ichi2.anki.cardviewer.SoundErrorListener import com.ichi2.anki.launchCatchingIO import com.ichi2.anki.pages.AnkiServer +import com.ichi2.anki.pages.PostRequestHandler import com.ichi2.libanki.Card import com.ichi2.libanki.Sound import com.ichi2.libanki.TtsPlayer @@ -46,7 +47,10 @@ import timber.log.Timber abstract class CardViewerViewModel( cardMediaPlayer: CardMediaPlayer -) : ViewModel(), OnErrorListener { +) : ViewModel(), + OnErrorListener, + PostRequestHandler { + override val onError = MutableSharedFlow() val onMediaError = MutableSharedFlow() val onTtsError = MutableSharedFlow() @@ -62,6 +66,8 @@ abstract class CardViewerViewModel( } abstract var currentCard: Deferred + abstract val server: AnkiServer + @CallSuper override fun onCleared() { super.onCleared() @@ -79,7 +85,7 @@ abstract class CardViewerViewModel( */ abstract fun onPageFinished(isAfterRecreation: Boolean) - open fun baseUrl(): String = "http://${AnkiServer.LOCALHOST}/" + fun baseUrl(): String = server.baseUrl() fun setSoundPlayerEnabled(isEnabled: Boolean) { cardMediaPlayer.isEnabled = isEnabled @@ -177,6 +183,17 @@ abstract class CardViewerViewModel( } } + override suspend fun handlePostRequest(uri: String, bytes: ByteArray): ByteArray { + return if (uri.startsWith(AnkiServer.ANKI_PREFIX)) { + when (uri.substring(AnkiServer.ANKI_PREFIX.length)) { + "i18nResources" -> withCol { i18nResourcesRaw(bytes) } + else -> throw IllegalArgumentException("Unhandled Anki request: $uri") + } + } else { + throw IllegalArgumentException("Unhandled POST request: $uri") + } + } + companion object { /* ********************************** Type-in answer ************************************ */ /** From the [desktop code](https://github.com/ankitects/anki/blob/1ff55475b93ac43748d513794bcaabd5d7df6d9d/qt/aqt/reviewer.py#L669] */ diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerViewModel.kt index fc02a21a69c1..0f4c810d4e25 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerViewModel.kt @@ -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.pages.AnkiServer import com.ichi2.anki.reviewer.CardSide import com.ichi2.anki.servicelayer.MARKED_TAG import com.ichi2.anki.servicelayer.NoteService @@ -67,6 +68,7 @@ class PreviewerViewModel(previewerIdsFile: PreviewerIdsFile, firstIndex: Int, ca override var currentCard: Deferred = asyncIO { withCol { getCard(selectedCardIds[firstIndex]) } } + override val server = AnkiServer(this).also { it.start() } /* ********************************************************************************************* ************************ Public methods: meant to be used by the View ************************** diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/TemplatePreviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/TemplatePreviewerViewModel.kt index a506c64eecde..ba5b2f758384 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/TemplatePreviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/TemplatePreviewerViewModel.kt @@ -26,6 +26,7 @@ import com.ichi2.anki.NotetypeFile import com.ichi2.anki.asyncIO import com.ichi2.anki.cardviewer.CardMediaPlayer import com.ichi2.anki.launchCatchingIO +import com.ichi2.anki.pages.AnkiServer import com.ichi2.anki.reviewer.CardSide import com.ichi2.anki.utils.ext.ifNullOrEmpty import com.ichi2.libanki.Card @@ -59,6 +60,7 @@ class TemplatePreviewerViewModel( private val templateNames: Deferred> private val clozeOrds: Deferred>? override var currentCard: Deferred + override val server = AnkiServer(this).also { it.start() } init { note = asyncIO { diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/scheduling/ForgetCardsViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/scheduling/ForgetCardsViewModel.kt index d9622f8e78b8..5a2cad9cf70e 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/scheduling/ForgetCardsViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/scheduling/ForgetCardsViewModel.kt @@ -19,7 +19,6 @@ package com.ichi2.anki.scheduling import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.ichi2.anki.CollectionManager.withCol -import com.ichi2.anki.pages.CardInfo import com.ichi2.libanki.CardId import kotlinx.coroutines.async import timber.log.Timber @@ -52,7 +51,7 @@ class ForgetCardsViewModel : ViewModel() { /** * Set the review and failure counters back to zero. * - * This does not affect [CardInfo]/review history + * This does not affect CardInfo/review history */ var resetRepetitionAndLapseCounts = false set(value) { diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt index 025a6656c938..54bea21586f2 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt @@ -25,7 +25,6 @@ import com.ichi2.anki.asyncIO import com.ichi2.anki.cardviewer.CardMediaPlayer import com.ichi2.anki.launchCatchingIO import com.ichi2.anki.pages.AnkiServer -import com.ichi2.anki.pages.PostRequestHandler import com.ichi2.anki.previewer.CardViewerViewModel import com.ichi2.anki.reviewer.CardSide import com.ichi2.libanki.sched.CurrentQueueState @@ -36,9 +35,7 @@ import kotlinx.coroutines.Deferred import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableSharedFlow -class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : - CardViewerViewModel(cardMediaPlayer), - PostRequestHandler { +class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel(cardMediaPlayer) { private var queueState: Deferred = asyncIO { // this assumes that the Reviewer won't be launched if there isn't a queueState @@ -49,7 +46,7 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : } var isQueueFinishedFlow = MutableSharedFlow() - private val server = AnkiServer(this).also { it.start() } + override val server = AnkiServer(this).also { it.start() } private val stateMutationKey = TimeManager.time.intTimeMS().toString() val statesMutationEval = MutableSharedFlow() @@ -85,8 +82,6 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : } } - override fun baseUrl(): String = server.baseUrl() - fun showAnswer() { launchCatchingIO { while (!statesMutated) { @@ -115,10 +110,10 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : when (uri.substring(AnkiServer.ANKI_PREFIX.length)) { "getSchedulingStatesWithContext" -> getSchedulingStatesWithContext() "setSchedulingStates" -> setSchedulingStates(bytes) - else -> byteArrayOf() + else -> super.handlePostRequest(uri, bytes) } } else { - byteArrayOf() + super.handlePostRequest(uri, bytes) } } diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/BackendImportExport.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/BackendImportExport.kt index d3b6aa6d18e4..f9172eaff59a 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/BackendImportExport.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/BackendImportExport.kt @@ -17,6 +17,8 @@ package com.ichi2.libanki import anki.import_export.ExportLimit +import anki.import_export.ImportAnkiPackageOptions +import anki.import_export.ImportResponse import anki.import_export.exportAnkiPackageOptions import anki.search.SearchNode import net.ankiweb.rsdroid.Backend @@ -92,6 +94,10 @@ fun Collection.exportCollectionPackage( reopen() } +fun Collection.importAnkiPackage(packagePath: String, options: ImportAnkiPackageOptions): ImportResponse { + return backend.importAnkiPackage(packagePath, options) +} + fun Collection.importAnkiPackageRaw(input: ByteArray): ByteArray { return backend.importAnkiPackageRaw(input) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b4ca516900b9..4819c1d2b6e7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,7 +25,7 @@ androidxUiautomator = "2.3.0" androidxViewpager2 = "1.1.0" androidxWebkit = "1.11.0" annotations = "24.1.0" -ankiBackend = '0.1.38-anki24.04.1' +ankiBackend = '0.1.39-anki24.06.2' autoService = "1.1.1" autoServiceAnnotations = "1.1.1" colorpicker = "1.2.0" From 3b6288a913b1705e2940b5ac607fcbdf69300be6 Mon Sep 17 00:00:00 2001 From: leobugeja Date: Sat, 1 Jun 2024 15:07:00 +0100 Subject: [PATCH 092/138] feat: Toggle check pronunciation feature --- .../src/main/java/com/ichi2/anki/MetaDB.kt | 64 ++++++++++++++++++- .../src/main/java/com/ichi2/anki/Reviewer.kt | 21 +++++- AnkiDroid/src/main/res/menu/reviewer.xml | 2 +- AnkiDroid/src/main/res/values/01-core.xml | 3 +- .../res/xml/preferences_custom_buttons.xml | 2 +- .../audio/AudioRecordingControllerTest.kt | 4 +- 6 files changed, 86 insertions(+), 10 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/MetaDB.kt b/AnkiDroid/src/main/java/com/ichi2/anki/MetaDB.kt index 65497d1d573f..edd3769f26af 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/MetaDB.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/MetaDB.kt @@ -33,7 +33,7 @@ object MetaDB { private const val DATABASE_NAME = "ankidroid.db" /** The Database Version, increase if you want updates to happen on next upgrade. */ - private const val DATABASE_VERSION = 7 + private const val DATABASE_VERSION = 8 /** The database object used by the meta-db. */ private var mMetaDb: SQLiteDatabase? = null @@ -74,6 +74,11 @@ object MetaDB { "CREATE TABLE IF NOT EXISTS smallWidgetStatus (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "due INTEGER NOT NULL, eta INTEGER NOT NULL)" ) + metaDb.execSQL( + "CREATE TABLE IF NOT EXISTS micToolbarState (" + "_id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "did INTEGER NOT NULL, state INTEGER NOT NULL)" + ) + updateWidgetStatus(metaDb) updateWhiteboardState(metaDb) metaDb.version = databaseVersion @@ -148,6 +153,8 @@ object MetaDB { Timber.i("MetaDB:: Resetting all language assignment") execSQL("DROP TABLE IF EXISTS whiteboardState;") Timber.i("MetaDB:: Resetting whiteboard state") + execSQL("DROP TABLE IF EXISTS micToolbarState;") + Timber.i("MetaDB:: Resetting mic toolbar state") execSQL("DROP TABLE IF EXISTS widgetStatus;") Timber.i("MetaDB:: Resetting widget status") execSQL("DROP TABLE IF EXISTS smallWidgetStatus;") @@ -287,7 +294,7 @@ object MetaDB { * Stores the state of the whiteboard for a given deck. * * @param did deck id to store whiteboard state for - * @param whiteboardState 1 if the whiteboard should be shown, 0 otherwise + * @param whiteboardState `true` if the whiteboard should be shown, `false` otherwise */ fun storeWhiteboardState(context: Context, did: DeckId, whiteboardState: Boolean) { val state = if (whiteboardState) 1 else 0 @@ -391,7 +398,7 @@ object MetaDB { * Stores the state of the whiteboard for a given deck. * * @param did deck id to store whiteboard state for - * @param isVisible 1 if the whiteboard should be shown, 0 otherwise + * @param isVisible `true` if the whiteboard should be shown, `false` otherwise */ fun storeWhiteboardVisibility(context: Context, did: DeckId, isVisible: Boolean) { val isVisibleState = if (isVisible) 1 else 0 @@ -476,6 +483,57 @@ object MetaDB { } } + /** + * Returns the state of the mic toolbar for the given deck. + * + * @return `true` if the toolbar should be shown, `false` otherwise + */ + fun getMicToolbarState(context: Context, did: DeckId): Boolean { + openDBIfClosed(context) + try { + mMetaDb!!.rawQuery( + "SELECT state FROM micToolbarState WHERE did = ?", + arrayOf(did.toString()) + ).use { cur -> return DatabaseUtil.getScalarBoolean(cur) } + } catch (e: Exception) { + Timber.e(e, "Error retrieving micToolbar state from MetaDB ") + return false + } + } + + /** + * Stores the state of the mic toolbar for a given deck. + * + * @param did deck id to store mic toolbar state for + * @param micToolbarState `true` if the toolbar should be shown, `false` otherwise + */ + fun storeMicToolbarState(context: Context, did: DeckId, isEnabled: Boolean) { + val state = if (isEnabled) 1 else 0 + openDBIfClosed(context) + try { + val metaDb = mMetaDb!! + metaDb.rawQuery( + "SELECT _id FROM micToolbarState WHERE did = ?", + arrayOf(did.toString()) + ).use { cur -> + if (cur.moveToNext()) { + metaDb.execSQL( + "UPDATE micToolbarState SET did = ?, state = ? WHERE _id = ?;", + arrayOf(did, state, cur.getString(0)) + ) + } else { + metaDb.execSQL( + "INSERT INTO micToolbarState (did, state) VALUES (?, ?)", + arrayOf(did, state) + ) + } + Timber.d("Store mic toolbar state (%d) for deck %d", state, did) + } + } catch (e: Exception) { + Timber.e(e, "Error storing mic toolbar state in MetaDB ") + } + } + /** * Return the current status of the widget. * diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt b/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt index 8d0d1c16290c..a63fa2523920 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt @@ -142,7 +142,7 @@ open class Reviewer : // Record Audio private var isMicToolBarVisible = false - /** Controller for 'Check Pronunciation' feature */ + /** Controller for 'Voice Playback' feature */ private var audioRecordingController: AudioRecordingController? = null private var isAudioUIInitialized = false private lateinit var micToolBarLayer: LinearLayout @@ -333,6 +333,12 @@ open class Reviewer : toggleStylus = MetaDB.getWhiteboardStylusState(this, parentDid) whiteboard!!.toggleStylus = toggleStylus } + + val isMicToolbarEnabled = MetaDB.getMicToolbarState(this, parentDid) + if (isMicToolbarEnabled) { + openMicToolbar() + } + launchCatchingTask { withCol { startTimebox() } updateCardAndRedraw() @@ -393,7 +399,7 @@ open class Reviewer : playSounds(true) } R.id.action_toggle_mic_tool_bar -> { - Timber.i("Reviewer:: Record mic") + Timber.i("Reviewer:: Voice playback visibility set to %b", !isMicToolBarVisible) // Check permission to record and request if not granted openOrToggleMicToolbar() } @@ -621,6 +627,10 @@ open class Reviewer : micToolBarLayer.visibility = View.VISIBLE } isMicToolBarVisible = !isMicToolBarVisible + + MetaDB.storeMicToolbarState(this, parentDid, isMicToolBarVisible) + + refreshActionBar() } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { @@ -819,6 +829,13 @@ open class Reviewer : menu.findItem(R.id.action_bury_card).isVisible = true } + val voicePlaybackIcon = menu.findItem(R.id.action_toggle_mic_tool_bar) + if (isMicToolBarVisible) { + voicePlaybackIcon.setTitle(R.string.menu_disable_voice_playback) + } else { + voicePlaybackIcon.setTitle(R.string.menu_enable_voice_playback) + } + onboarding.onCreate() increaseHorizontalPaddingOfOverflowMenuIcons(menu) diff --git a/AnkiDroid/src/main/res/menu/reviewer.xml b/AnkiDroid/src/main/res/menu/reviewer.xml index f68d32f751ba..45ffd00c309a 100644 --- a/AnkiDroid/src/main/res/menu/reviewer.xml +++ b/AnkiDroid/src/main/res/menu/reviewer.xml @@ -148,7 +148,7 @@ ankidroid:showAsAction="ifRoom"/> Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/xml/preferences_custom_buttons.xml b/AnkiDroid/src/main/res/xml/preferences_custom_buttons.xml index 7587e974240b..b8bf97ab3a43 100644 --- a/AnkiDroid/src/main/res/xml/preferences_custom_buttons.xml +++ b/AnkiDroid/src/main/res/xml/preferences_custom_buttons.xml @@ -123,7 +123,7 @@ TODO: Add a unit test android:entries="@array/custom_button_labels" android:entryValues="@array/custom_button_values" android:key="@string/custom_button_toggle_mic_toolbar_key" - android:title="@string/menu_toggle_mic_tool_bar" + android:title="@string/menu_enable_voice_playback" app:useSimpleSummaryProvider="true"/> diff --git a/AnkiDroid/src/test/java/com/ichi2/audio/AudioRecordingControllerTest.kt b/AnkiDroid/src/test/java/com/ichi2/audio/AudioRecordingControllerTest.kt index 3581daee2d49..b7f1d48b6fd8 100644 --- a/AnkiDroid/src/test/java/com/ichi2/audio/AudioRecordingControllerTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/audio/AudioRecordingControllerTest.kt @@ -46,7 +46,7 @@ class AudioRecordingControllerAndroidTest : RobolectricTest() { @Test @Ignore("does not fail when expected under Robolectric") - fun `Check Pronunciation handles onPause`() = withCheckPronunciation { + fun `Voice Playback handles onPause`() = withVoicePlayback { Timber.v("start recording") layout.findViewById(R.id.action_start_recording).performClick() Timber.v("stop recording") @@ -59,7 +59,7 @@ class AudioRecordingControllerAndroidTest : RobolectricTest() { } /** Applies [block] to a [AudioRecordingController] generated for the [Reviewer] */ - private fun withCheckPronunciation(block: AudioRecordingController.() -> Unit) { + private fun withVoicePlayback(block: AudioRecordingController.() -> Unit) { ShadowMediaPlayer.setMediaInfoProvider { ShadowMediaPlayer.MediaInfo(200, 1) } val layout = LinearLayout(targetContext) Themes.setTheme(targetContext) From 8e0b537b1d9fe464a82dad68e8bc744c1cbced4c Mon Sep 17 00:00:00 2001 From: Aditya kumar Date: Sat, 25 May 2024 15:01:07 +0530 Subject: [PATCH 093/138] Undo was showing even if it is unavailable (fixed) --- .../main/java/com/ichi2/anki/DeckPicker.kt | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt b/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt index 5e9245139304..c53de86f7c49 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt @@ -953,16 +953,20 @@ open class DeckPicker : menu.setGroupVisible(R.id.allItems, optionsMenuState != null) optionsMenuState?.run { menu.findItem(R.id.deck_picker_action_filter).isVisible = searchIcon - updateUndoLabelFromState(menu.findItem(R.id.action_undo), undoLabel) + updateUndoLabelFromState(menu.findItem(R.id.action_undo), undoLabel, undoAvailable) updateSyncIconFromState(menu.findItem(R.id.action_sync), this) menu.findItem(R.id.action_scoped_storage_migrate).isVisible = shouldShowStartMigrationButton setupMigrationProgressMenuItem(menu, mediaMigrationState) } } - private fun updateUndoLabelFromState(menuItem: MenuItem, undoLabel: String?) { + private fun updateUndoLabelFromState( + menuItem: MenuItem, + undoLabel: String?, + undoAvailable: Boolean + ) { menuItem.run { - if (undoLabel != null) { + if (undoLabel != null && undoAvailable) { isVisible = true title = undoLabel } else { @@ -1011,13 +1015,14 @@ open class DeckPicker : optionsMenuState = withOpenColOrNull { val searchIcon = decks.count() >= 10 val undoLabel = undoLabel() - Pair(searchIcon, undoLabel) - }?.let { (searchIcon, undoLabel) -> + val undoAvailable = undoAvailable() + Triple(searchIcon, undoLabel, undoAvailable) + }?.let { (searchIcon, undoLabel, undoAvailable) -> val syncIcon = fetchSyncStatus() val mediaMigrationState = getMediaMigrationState() val shouldShowStartMigrationButton = shouldOfferToMigrate() || mediaMigrationState is MediaMigrationState.Ongoing.PausedDueToError - OptionsMenuState(searchIcon, undoLabel, syncIcon, shouldShowStartMigrationButton, mediaMigrationState) + OptionsMenuState(searchIcon, undoLabel, syncIcon, shouldShowStartMigrationButton, mediaMigrationState, undoAvailable) } } @@ -2043,6 +2048,8 @@ open class DeckPicker : Pair(sched.deckDueTree(), this.isEmpty) } onDecksLoaded(deckData.first, deckData.second) + + updateMenuState() } } } @@ -2704,7 +2711,8 @@ data class OptionsMenuState( val undoLabel: String?, val syncIcon: SyncIconState, val shouldShowStartMigrationButton: Boolean, - val mediaMigrationState: MediaMigrationState + val mediaMigrationState: MediaMigrationState, + val undoAvailable: Boolean ) enum class SyncIconState { From 03dff23f9bbaca852a933c5a95dce70b257354e1 Mon Sep 17 00:00:00 2001 From: AnkiDroid Translations Date: Tue, 18 Jun 2024 19:13:55 +0000 Subject: [PATCH 094/138] Updated strings from Crowdin --- AnkiDroid/src/main/res/values-af/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-am/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ar/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-az/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-be/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-bg/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-bn/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ca/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ckb/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-cs/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-da/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-de/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-el/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-eo/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-es-rAR/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-es-rES/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-et/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-eu/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-fa/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-fi/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-fil/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-fr/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-fy/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ga/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-gl/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-got/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-gu/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-heb/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-hi/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-hr/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-hu/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-hy/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ind/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-is/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-it/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-iw/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ja/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-jv/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ka/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-kk/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-km/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-kn/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ko/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ku/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ky/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-lt/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-lv/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-mk/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ml/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-mn/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-mr/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ms/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-my/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-nl/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-nn/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-no/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-or/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-pa/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-pl/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-pt-rBR/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-pt-rPT/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ro/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ru/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-sat/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-sc/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-sk/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-sl/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-sq/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-sr/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ss/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-sv/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-sw/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ta/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-te/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-tg/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-tgl/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-th/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ti/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-tn/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-tr/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ts/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-tt/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-uk/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ur/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-uz/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-ve/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-vi/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-wo/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-xh/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-yue/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-zh-rCN/01-core.xml | 5 +++-- AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml | 2 +- AnkiDroid/src/main/res/values-zh-rTW/01-core.xml | 3 ++- AnkiDroid/src/main/res/values-zu/01-core.xml | 3 ++- 94 files changed, 188 insertions(+), 95 deletions(-) diff --git a/AnkiDroid/src/main/res/values-af/01-core.xml b/AnkiDroid/src/main/res/values-af/01-core.xml index 9636e17884ee..1c6fdff4d2a8 100644 --- a/AnkiDroid/src/main/res/values-af/01-core.xml +++ b/AnkiDroid/src/main/res/values-af/01-core.xml @@ -111,7 +111,8 @@ Soek in %1$s Merk nota Ontmerk - Sien uitspraak na + Enable voice playback + Disable voice playback Skep pak Skep gefiltreerde kaartpak AnkiDroid gids is onbereikbaar diff --git a/AnkiDroid/src/main/res/values-am/01-core.xml b/AnkiDroid/src/main/res/values-am/01-core.xml index d9833f3293b9..9a55242b2de5 100644 --- a/AnkiDroid/src/main/res/values-am/01-core.xml +++ b/AnkiDroid/src/main/res/values-am/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-ar/01-core.xml b/AnkiDroid/src/main/res/values-ar/01-core.xml index 9a2811b2c651..af14fdfe7b5a 100644 --- a/AnkiDroid/src/main/res/values-ar/01-core.xml +++ b/AnkiDroid/src/main/res/values-ar/01-core.xml @@ -123,7 +123,8 @@ البحث في %1$s تأشير الملحوظة إلغاء تأشير الملحوظة - تحقق من النطق + Enable voice playback + Disable voice playback إنشاء رزمة إنشاء رزمة مفلترة لا يمكن الوصول لمجلد آنكيدرويد diff --git a/AnkiDroid/src/main/res/values-az/01-core.xml b/AnkiDroid/src/main/res/values-az/01-core.xml index 565497cad9dc..f6ebc538f01c 100644 --- a/AnkiDroid/src/main/res/values-az/01-core.xml +++ b/AnkiDroid/src/main/res/values-az/01-core.xml @@ -111,7 +111,8 @@ %1$s içində axtar Qeydi işarələ İşarəni götür - Səsi yoxlayın + Enable voice playback + Disable voice playback Dəstə yarat Filtrli dəstə yarat AnkiDroid kataloqu əlçatmazdır diff --git a/AnkiDroid/src/main/res/values-be/01-core.xml b/AnkiDroid/src/main/res/values-be/01-core.xml index d47be82ba7f5..25740c8208fb 100644 --- a/AnkiDroid/src/main/res/values-be/01-core.xml +++ b/AnkiDroid/src/main/res/values-be/01-core.xml @@ -117,7 +117,8 @@ Шукаць у %1$s Пазначыць нататку Зняць пазнаку з нататкі - Праверыць вымаўленне + Enable voice playback + Disable voice playback Стварыць калоду Стварыць фільтраваную калоду Каталог AnkiDroid недаступны diff --git a/AnkiDroid/src/main/res/values-bg/01-core.xml b/AnkiDroid/src/main/res/values-bg/01-core.xml index 04b36bd9929a..af466dd47567 100644 --- a/AnkiDroid/src/main/res/values-bg/01-core.xml +++ b/AnkiDroid/src/main/res/values-bg/01-core.xml @@ -111,7 +111,8 @@ Търсене в %1$s Маркирай бележка Размаркирай бележка - Проверете произношението + Enable voice playback + Disable voice playback Създай тесте Създайте филтрирано тесте AnkiDroid директорията е недостъпна diff --git a/AnkiDroid/src/main/res/values-bn/01-core.xml b/AnkiDroid/src/main/res/values-bn/01-core.xml index 06164fe3f9d5..385e5587c8fe 100644 --- a/AnkiDroid/src/main/res/values-bn/01-core.xml +++ b/AnkiDroid/src/main/res/values-bn/01-core.xml @@ -111,7 +111,8 @@ অনুসন্ধান করুন %1$s টীকা চিহ্ন নোটের টীকা চিহ্ন মুছুন - উচ্চারণ চেক করো + Enable voice playback + Disable voice playback ডেক তৈরি করুন ফিল্টার করা ডেক তৈরি করুন আনকিড্রইড ডাইরেক্টরি অপ্রবেশ্য। diff --git a/AnkiDroid/src/main/res/values-ca/01-core.xml b/AnkiDroid/src/main/res/values-ca/01-core.xml index 49e980668bfc..a2482f556a58 100644 --- a/AnkiDroid/src/main/res/values-ca/01-core.xml +++ b/AnkiDroid/src/main/res/values-ca/01-core.xml @@ -111,7 +111,8 @@ Cerca-ho a %1$s Marcar nota Desmarcar - Comprova pronunciació + Enable voice playback + Disable voice playback Crea un paquet Crear un paquet filtrat El directori d\'AnkiDroid és inaccessible diff --git a/AnkiDroid/src/main/res/values-ckb/01-core.xml b/AnkiDroid/src/main/res/values-ckb/01-core.xml index 4358e5ee9edb..e5d96e4fefd0 100644 --- a/AnkiDroid/src/main/res/values-ckb/01-core.xml +++ b/AnkiDroid/src/main/res/values-ckb/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback دروستکردنی دەستە Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-cs/01-core.xml b/AnkiDroid/src/main/res/values-cs/01-core.xml index f11fe4bd545d..9022a2f6cd06 100644 --- a/AnkiDroid/src/main/res/values-cs/01-core.xml +++ b/AnkiDroid/src/main/res/values-cs/01-core.xml @@ -117,7 +117,8 @@ Vyhledat v %1$s Označit poznámku Odznačit poznámku - Zkontrolovat výslovnost + Enable voice playback + Disable voice playback Vytvořit balíček Vytvořit filtrovaný balíček AnkiDroid adresář není přístupný diff --git a/AnkiDroid/src/main/res/values-da/01-core.xml b/AnkiDroid/src/main/res/values-da/01-core.xml index 32a9f70f6030..158ad4dff12b 100644 --- a/AnkiDroid/src/main/res/values-da/01-core.xml +++ b/AnkiDroid/src/main/res/values-da/01-core.xml @@ -111,7 +111,8 @@ Slå op i %1$s Markér note Afmarkér note - Tjek udtale + Enable voice playback + Disable voice playback Opret stak Opret filtreret stak AnkiDroid-mappen er utilgængelig diff --git a/AnkiDroid/src/main/res/values-de/01-core.xml b/AnkiDroid/src/main/res/values-de/01-core.xml index da8f710e9eed..d1ac9cc323a0 100644 --- a/AnkiDroid/src/main/res/values-de/01-core.xml +++ b/AnkiDroid/src/main/res/values-de/01-core.xml @@ -111,7 +111,8 @@ In %1$s nachschlagen Notiz markieren Markierung entfernen - Aussprache überprüfen + Enable voice playback + Disable voice playback Stapel erstellen Gefilterten Stapel erstellen Auf das AnkiDroid-Verzeichnis kann nicht zugegriffen werden diff --git a/AnkiDroid/src/main/res/values-el/01-core.xml b/AnkiDroid/src/main/res/values-el/01-core.xml index 96969934fc89..09fa8dd6ce1d 100644 --- a/AnkiDroid/src/main/res/values-el/01-core.xml +++ b/AnkiDroid/src/main/res/values-el/01-core.xml @@ -111,7 +111,8 @@ Αναζήτηση στο %1$s Μαρκάρισμα σημείωσης Ξεμαρκάρισμα σημείωσης - Έλεγχος προφοράς + Enable voice playback + Disable voice playback Δημιουργία τράπουλας Δημιουργία φιλτραρισμένης τράπουλας Η τοποθεσία τού AnkiDroid είναι μη προσβάσιμη diff --git a/AnkiDroid/src/main/res/values-eo/01-core.xml b/AnkiDroid/src/main/res/values-eo/01-core.xml index 4c4ae59dbac6..eb2a51008164 100644 --- a/AnkiDroid/src/main/res/values-eo/01-core.xml +++ b/AnkiDroid/src/main/res/values-eo/01-core.xml @@ -111,7 +111,8 @@ Serĉi en %1$s Marki noton Malmarki noton - Kontroli elparolon + Enable voice playback + Disable voice playback Krei kartaron Krei filtritan kartaron Dosierujo de AnkiDroid estas nealirebla diff --git a/AnkiDroid/src/main/res/values-es-rAR/01-core.xml b/AnkiDroid/src/main/res/values-es-rAR/01-core.xml index fb3649b6a7cc..2c2e843c6ba0 100644 --- a/AnkiDroid/src/main/res/values-es-rAR/01-core.xml +++ b/AnkiDroid/src/main/res/values-es-rAR/01-core.xml @@ -111,7 +111,8 @@ Revisión en %1$s Marcar nota Desmarcar nota - Comprobar pronunciación + Enable voice playback + Disable voice playback Crear mazo Crear mazo filtrado No se puede acceder a la carpeta de AnkiDroid diff --git a/AnkiDroid/src/main/res/values-es-rES/01-core.xml b/AnkiDroid/src/main/res/values-es-rES/01-core.xml index 969e4f0daa6b..d04c8efaa499 100644 --- a/AnkiDroid/src/main/res/values-es-rES/01-core.xml +++ b/AnkiDroid/src/main/res/values-es-rES/01-core.xml @@ -111,7 +111,8 @@ Búsqueda en %1$s Marcar nota Desmarcar nota - Comprobar pronunciación + Enable voice playback + Disable voice playback Crear mazo Crear mazo filtrado El directorio AnkiDroid es inaccesible diff --git a/AnkiDroid/src/main/res/values-et/01-core.xml b/AnkiDroid/src/main/res/values-et/01-core.xml index 356462a410bf..f42c1e597bb9 100644 --- a/AnkiDroid/src/main/res/values-et/01-core.xml +++ b/AnkiDroid/src/main/res/values-et/01-core.xml @@ -111,7 +111,8 @@ Otsi %1$s Tähista märge Eemalda tähistus märkelt - Kontrolli hääldust + Enable voice playback + Disable voice playback Loo kaardipakk Loo filtritud kaardipakk Ei saa ligi kaustale \"AnkiDroid\" diff --git a/AnkiDroid/src/main/res/values-eu/01-core.xml b/AnkiDroid/src/main/res/values-eu/01-core.xml index e0691d249f14..45d2e2ede7f9 100644 --- a/AnkiDroid/src/main/res/values-eu/01-core.xml +++ b/AnkiDroid/src/main/res/values-eu/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Markatu oharra Desmarkatu oharra - Check pronunciation + Enable voice playback + Disable voice playback Sortu sorta Sortu iragazitako sorta AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-fa/01-core.xml b/AnkiDroid/src/main/res/values-fa/01-core.xml index 3636499557ec..de41e366a946 100644 --- a/AnkiDroid/src/main/res/values-fa/01-core.xml +++ b/AnkiDroid/src/main/res/values-fa/01-core.xml @@ -111,7 +111,8 @@ جستجو در %1$s علامتگذاری یادداشت برداشتن علامتگذاری یادداشت - بررسی تلفظ + Enable voice playback + Disable voice playback ایجاد دسته ایجاد دسته فیلتر شده فهرست AnkiDroid غیر قابل دسترس است diff --git a/AnkiDroid/src/main/res/values-fi/01-core.xml b/AnkiDroid/src/main/res/values-fi/01-core.xml index 5fee103f1aac..a72a405e475a 100644 --- a/AnkiDroid/src/main/res/values-fi/01-core.xml +++ b/AnkiDroid/src/main/res/values-fi/01-core.xml @@ -111,7 +111,8 @@ Haku %1$s Merkitse merkintä Poista merkintä - Tarkista ääntäminen + Enable voice playback + Disable voice playback Uusi pakka Uusi suodatettu pakka AnkiDroidin hakemisto ei ole käytettävissä diff --git a/AnkiDroid/src/main/res/values-fil/01-core.xml b/AnkiDroid/src/main/res/values-fil/01-core.xml index 74839d389773..d9ea595a0ab2 100644 --- a/AnkiDroid/src/main/res/values-fil/01-core.xml +++ b/AnkiDroid/src/main/res/values-fil/01-core.xml @@ -111,7 +111,8 @@ Hanapin sa %1$s Markahan ang tala Alisin ang marka sa tala - Suriin ang pagbigkas + Enable voice playback + Disable voice playback Gumawa ng deck Gumawa ng na-filter na deck Hindi mapuntahan ang AnkiDroid directory diff --git a/AnkiDroid/src/main/res/values-fr/01-core.xml b/AnkiDroid/src/main/res/values-fr/01-core.xml index 308bd05bcbd8..8e029f084f6f 100644 --- a/AnkiDroid/src/main/res/values-fr/01-core.xml +++ b/AnkiDroid/src/main/res/values-fr/01-core.xml @@ -111,7 +111,8 @@ Trouvé en %1$s Marquer la note Démarquer la note - Vérifier la prononciation + Enable voice playback + Disable voice playback Créer un jeu de cartes Créer un paquet filtré Le répertoire d\'AnkiDroid est inaccessible diff --git a/AnkiDroid/src/main/res/values-fy/01-core.xml b/AnkiDroid/src/main/res/values-fy/01-core.xml index a7d747a1b254..260be0aeaa76 100644 --- a/AnkiDroid/src/main/res/values-fy/01-core.xml +++ b/AnkiDroid/src/main/res/values-fy/01-core.xml @@ -111,7 +111,8 @@ Opsykje yn %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Set meitsje Gefilterde set meitsjen AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-ga/01-core.xml b/AnkiDroid/src/main/res/values-ga/01-core.xml index a6f227397140..c4efe4e834d7 100644 --- a/AnkiDroid/src/main/res/values-ga/01-core.xml +++ b/AnkiDroid/src/main/res/values-ga/01-core.xml @@ -120,7 +120,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-gl/01-core.xml b/AnkiDroid/src/main/res/values-gl/01-core.xml index 382e9f2aaf3f..a52e0e97132f 100644 --- a/AnkiDroid/src/main/res/values-gl/01-core.xml +++ b/AnkiDroid/src/main/res/values-gl/01-core.xml @@ -111,7 +111,8 @@ Procurar en %1$s Marcar nota Desmarcar nota - comprobar pronunciación + Enable voice playback + Disable voice playback Crear baralla Crear baralla filtrada O directorio AnkiDroid non está accesible diff --git a/AnkiDroid/src/main/res/values-got/01-core.xml b/AnkiDroid/src/main/res/values-got/01-core.xml index 24ecf8960d23..ae2421bf4fdf 100644 --- a/AnkiDroid/src/main/res/values-got/01-core.xml +++ b/AnkiDroid/src/main/res/values-got/01-core.xml @@ -111,7 +111,8 @@ Gasokei in %1$s Gatarhei melein Ungatarhei melein - Check pronunciation + Enable voice playback + Disable voice playback Skapei wikon Skapei wikon mi AnkiDroid staþ atgaggan mahts nist diff --git a/AnkiDroid/src/main/res/values-gu/01-core.xml b/AnkiDroid/src/main/res/values-gu/01-core.xml index 7f539512c684..1269f5b9c092 100644 --- a/AnkiDroid/src/main/res/values-gu/01-core.xml +++ b/AnkiDroid/src/main/res/values-gu/01-core.xml @@ -111,7 +111,8 @@ %1$s માં જુઓ નોંધ ચિહ્નિત કરો ચિહ્નિત નોંધોમાથી કાઢો - ઊચ્ચારણ તપાસો + Enable voice playback + Disable voice playback થપ્પી ઉમેરો ફિલ્ટર કરેલ ડેક બનાવો AnkiDroid શબ્દાવલિ પહોંચ બહાર છે diff --git a/AnkiDroid/src/main/res/values-heb/01-core.xml b/AnkiDroid/src/main/res/values-heb/01-core.xml index b09437783c78..5c10e98bb067 100644 --- a/AnkiDroid/src/main/res/values-heb/01-core.xml +++ b/AnkiDroid/src/main/res/values-heb/01-core.xml @@ -118,7 +118,8 @@ חפש ב%1$s סמן רשומה הסר סימון רשומה - בדוק הגיה + Enable voice playback + Disable voice playback יצירת חפיסה יצירת חפיסה מסוננת הספרייה של AnkiDroid אינה נגישה diff --git a/AnkiDroid/src/main/res/values-hi/01-core.xml b/AnkiDroid/src/main/res/values-hi/01-core.xml index f338cc52274b..309b1baabed6 100644 --- a/AnkiDroid/src/main/res/values-hi/01-core.xml +++ b/AnkiDroid/src/main/res/values-hi/01-core.xml @@ -111,7 +111,8 @@ लुकअप में %1$s नोट चिह्नित करें नोट अचिह्नित करें - आप उच्चारण जाँचिये + Enable voice playback + Disable voice playback डेक बनाने फ़िल्टर्ड डेक बनाएं AnkiDroid निर्देशिका पहुंच योग्य नहीं है diff --git a/AnkiDroid/src/main/res/values-hr/01-core.xml b/AnkiDroid/src/main/res/values-hr/01-core.xml index b2358fa71c44..0a5f557cb972 100644 --- a/AnkiDroid/src/main/res/values-hr/01-core.xml +++ b/AnkiDroid/src/main/res/values-hr/01-core.xml @@ -114,7 +114,8 @@ Traži u %1$s Označi bilješku Odznači bilješku - Provjeri izgovor + Enable voice playback + Disable voice playback Stvori skupinu Stvori filtriranu skupinu AnkiDroid mapa nije dostupna diff --git a/AnkiDroid/src/main/res/values-hu/01-core.xml b/AnkiDroid/src/main/res/values-hu/01-core.xml index 98c20cf27b7a..13aa795fc676 100644 --- a/AnkiDroid/src/main/res/values-hu/01-core.xml +++ b/AnkiDroid/src/main/res/values-hu/01-core.xml @@ -111,7 +111,8 @@ Keresés itt: %1$s Jegyzet megjelölése Jegyzet megjelölés megszüntetése - Kiejtés ellenőrzése + Enable voice playback + Disable voice playback Pakli létrehozása Szűrt pakli létrehozása Nem érhető el az AnkiDroid könyvtár diff --git a/AnkiDroid/src/main/res/values-hy/01-core.xml b/AnkiDroid/src/main/res/values-hy/01-core.xml index 6e117cc7f46c..b87ceb8adb82 100644 --- a/AnkiDroid/src/main/res/values-hy/01-core.xml +++ b/AnkiDroid/src/main/res/values-hy/01-core.xml @@ -111,7 +111,8 @@ Որոնում %1$s-ում Նշել գրառումը Ապանշել գրառումը - Արտասանության ստուգում + Enable voice playback + Disable voice playback Ստեղծել կապուկ Ստեղծել զտված կապուկ AnkiDroid-ի պանակը անհասանելի է diff --git a/AnkiDroid/src/main/res/values-ind/01-core.xml b/AnkiDroid/src/main/res/values-ind/01-core.xml index 2164cdb0a7e9..7183412271c5 100644 --- a/AnkiDroid/src/main/res/values-ind/01-core.xml +++ b/AnkiDroid/src/main/res/values-ind/01-core.xml @@ -108,7 +108,8 @@ Pencarian di %1$s Tandai catatan Batal tandai catatan - Cek pelafalan + Enable voice playback + Disable voice playback Buat dek Buat dek terfilter Direktori AnkiDroid tidak dapat diakses diff --git a/AnkiDroid/src/main/res/values-is/01-core.xml b/AnkiDroid/src/main/res/values-is/01-core.xml index 138e24d3a994..dcd1832ad47c 100644 --- a/AnkiDroid/src/main/res/values-is/01-core.xml +++ b/AnkiDroid/src/main/res/values-is/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-it/01-core.xml b/AnkiDroid/src/main/res/values-it/01-core.xml index a1be96ce79c6..84ef27bc782d 100644 --- a/AnkiDroid/src/main/res/values-it/01-core.xml +++ b/AnkiDroid/src/main/res/values-it/01-core.xml @@ -111,7 +111,8 @@ Ricerca in %1$s Contrassegna nota Rimuovi contrassegno nota - Controlla pronuncia + Enable voice playback + Disable voice playback Crea mazzo Crea mazzo filtrato La directory AnkiDroid è inaccessibile diff --git a/AnkiDroid/src/main/res/values-iw/01-core.xml b/AnkiDroid/src/main/res/values-iw/01-core.xml index b09437783c78..5c10e98bb067 100644 --- a/AnkiDroid/src/main/res/values-iw/01-core.xml +++ b/AnkiDroid/src/main/res/values-iw/01-core.xml @@ -118,7 +118,8 @@ חפש ב%1$s סמן רשומה הסר סימון רשומה - בדוק הגיה + Enable voice playback + Disable voice playback יצירת חפיסה יצירת חפיסה מסוננת הספרייה של AnkiDroid אינה נגישה diff --git a/AnkiDroid/src/main/res/values-ja/01-core.xml b/AnkiDroid/src/main/res/values-ja/01-core.xml index 5f4b8b329800..d9e5883d54ab 100644 --- a/AnkiDroid/src/main/res/values-ja/01-core.xml +++ b/AnkiDroid/src/main/res/values-ja/01-core.xml @@ -108,7 +108,8 @@ %1$s で検索 ノートにマークを付ける ノートのマークをはずす - 自分の発音を確認 + Enable voice playback + Disable voice playback デッキを新規作成 フィルターデッキを作成 AnkiDroidディレクトリにアクセスできません diff --git a/AnkiDroid/src/main/res/values-jv/01-core.xml b/AnkiDroid/src/main/res/values-jv/01-core.xml index 8dbd9c12516f..ea7b9e5202b3 100644 --- a/AnkiDroid/src/main/res/values-jv/01-core.xml +++ b/AnkiDroid/src/main/res/values-jv/01-core.xml @@ -108,7 +108,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-ka/01-core.xml b/AnkiDroid/src/main/res/values-ka/01-core.xml index a4e822adb23d..9aa0a7584c96 100644 --- a/AnkiDroid/src/main/res/values-ka/01-core.xml +++ b/AnkiDroid/src/main/res/values-ka/01-core.xml @@ -111,7 +111,8 @@ მონახულება %1$s-ში მონიშნე შენიშვნა შენიშვნის გაუქმება - გამოთქმის შემოწმება + Enable voice playback + Disable voice playback დასტის შექმნა ფილტრირებული დასტის შექმნა AnkiDroid-ის ბიბლიოთეკა მიუწვდომელია diff --git a/AnkiDroid/src/main/res/values-kk/01-core.xml b/AnkiDroid/src/main/res/values-kk/01-core.xml index df49724922e6..2341de22794d 100644 --- a/AnkiDroid/src/main/res/values-kk/01-core.xml +++ b/AnkiDroid/src/main/res/values-kk/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-km/01-core.xml b/AnkiDroid/src/main/res/values-km/01-core.xml index e7ffb1997024..e64fb80fabe6 100644 --- a/AnkiDroid/src/main/res/values-km/01-core.xml +++ b/AnkiDroid/src/main/res/values-km/01-core.xml @@ -108,7 +108,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-kn/01-core.xml b/AnkiDroid/src/main/res/values-kn/01-core.xml index fd5f3d54cf91..571c20302954 100644 --- a/AnkiDroid/src/main/res/values-kn/01-core.xml +++ b/AnkiDroid/src/main/res/values-kn/01-core.xml @@ -111,7 +111,8 @@ %1$s ನಲ್ಲಿ ಹುಡುಕಿ ಟಿಪ್ಪಣಿ ಗುರುತಿಸಿ ಟಿಪ್ಪಣಿ ಗುರುತು - ಉಚ್ಚಾರಣೆಯನ್ನು ಪರಿಶೀಲಿಸಿ + Enable voice playback + Disable voice playback ಸಂಗ್ರಹವನ್ನು ರಚಿಸಿ ಫಿಲ್ಟರ್ ಮಾಡಿದ ಸಂಗ್ರಹ ರಚಿಸಿ ಆಂಕಿಡ್ರಾಯ್ಡ್ ಡೈರೆಕ್ಟರಿ ಪ್ರವೇಶಿಸಲಾಗುವುದಿಲ್ಲ diff --git a/AnkiDroid/src/main/res/values-ko/01-core.xml b/AnkiDroid/src/main/res/values-ko/01-core.xml index ce336ba6a544..f1801c8bf0f9 100644 --- a/AnkiDroid/src/main/res/values-ko/01-core.xml +++ b/AnkiDroid/src/main/res/values-ko/01-core.xml @@ -108,7 +108,8 @@ %1$s에서 찾아보기 노트 표시 노트 표시 해제 - 발음 확인 + Enable voice playback + Disable voice playback 카드 묶음 만들기 필터링된 카드 묶음 만들기 AnkiDroid 폴더에 접근할 수 없습니다 diff --git a/AnkiDroid/src/main/res/values-ku/01-core.xml b/AnkiDroid/src/main/res/values-ku/01-core.xml index 44e3a5e7e855..29db2a003a7b 100644 --- a/AnkiDroid/src/main/res/values-ku/01-core.xml +++ b/AnkiDroid/src/main/res/values-ku/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-ky/01-core.xml b/AnkiDroid/src/main/res/values-ky/01-core.xml index 7b620020eaf4..105caf112cf7 100644 --- a/AnkiDroid/src/main/res/values-ky/01-core.xml +++ b/AnkiDroid/src/main/res/values-ky/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-lt/01-core.xml b/AnkiDroid/src/main/res/values-lt/01-core.xml index 84f99f8b437b..d7dfb44eec45 100644 --- a/AnkiDroid/src/main/res/values-lt/01-core.xml +++ b/AnkiDroid/src/main/res/values-lt/01-core.xml @@ -117,7 +117,8 @@ Ieškoti: %1$s Žymėti užrašą Atžymėti užrašą - Patikrinti tarimą + Enable voice playback + Disable voice playback Kurti rinkinį Kurti rinktinį rinkinį „AnkiDroid“ katalogas yra nepasiekiamas diff --git a/AnkiDroid/src/main/res/values-lv/01-core.xml b/AnkiDroid/src/main/res/values-lv/01-core.xml index 1e9736047448..351feb77689e 100644 --- a/AnkiDroid/src/main/res/values-lv/01-core.xml +++ b/AnkiDroid/src/main/res/values-lv/01-core.xml @@ -114,7 +114,8 @@ Meklēt iekš %1$s Atzīmēt rakstu Neatzīmēt rakstu - Pārbaudīt izrunu + Enable voice playback + Disable voice playback Izveidot kavu Izveidot pielāgotu kavu AnkiDroid krātuve nav pieejama diff --git a/AnkiDroid/src/main/res/values-mk/01-core.xml b/AnkiDroid/src/main/res/values-mk/01-core.xml index 47d98f9e835c..b26cca2f0f05 100644 --- a/AnkiDroid/src/main/res/values-mk/01-core.xml +++ b/AnkiDroid/src/main/res/values-mk/01-core.xml @@ -111,7 +111,8 @@ Пребарување во %1$s Означите белешка Отштиклирај ја белешката - Провери изговор + Enable voice playback + Disable voice playback Креирајте deck Креирајте филтер на deck AnkiDroid директориумот е недостапен diff --git a/AnkiDroid/src/main/res/values-ml/01-core.xml b/AnkiDroid/src/main/res/values-ml/01-core.xml index 6b56736457a0..78b82d4f0a25 100644 --- a/AnkiDroid/src/main/res/values-ml/01-core.xml +++ b/AnkiDroid/src/main/res/values-ml/01-core.xml @@ -111,7 +111,8 @@ %1$s ൽ തിരയുക കുറിപ്പ് അടയാളപ്പെടുത്തുക കുറിപ്പ് അടയാളപ്പെടുത്തുക - ഉച്ചാരണം പരിശോധിക്കുക + Enable voice playback + Disable voice playback ഡെക്ക് സൃഷ്ടിക്കുക ഫിൽട്ടർ ചെയ്ത ഡെക്ക് സൃഷ്ടിക്കുക AnkiDroid ഡയറക്‌ടറി ആക്‌സസ്സുചെയ്യാനാകില്ല diff --git a/AnkiDroid/src/main/res/values-mn/01-core.xml b/AnkiDroid/src/main/res/values-mn/01-core.xml index a4616556f5d0..9d67cdc6b0fb 100644 --- a/AnkiDroid/src/main/res/values-mn/01-core.xml +++ b/AnkiDroid/src/main/res/values-mn/01-core.xml @@ -111,7 +111,8 @@ %1$s ын дараа дахин харагдана Картын хэсэгт тэмдэглэл нэмэх Картын хэсгийн тэмдэглэлийг хасах - Дуудлагийг шалгах + Enable voice playback + Disable voice playback Багц бүтээх Ангилсан багц бүтээх Анкидройдын файлуудын чиглэсэн чиглэл ашиглах боломжгүй байна diff --git a/AnkiDroid/src/main/res/values-mr/01-core.xml b/AnkiDroid/src/main/res/values-mr/01-core.xml index c2cbb69792c2..ec92e402e988 100644 --- a/AnkiDroid/src/main/res/values-mr/01-core.xml +++ b/AnkiDroid/src/main/res/values-mr/01-core.xml @@ -111,7 +111,8 @@ %1$s मध्ये पहा चिन्हांकित करा अचिन्हांची नोंद - उच्चारण तपासा + Enable voice playback + Disable voice playback डेक तयार करा फिल्टर केलेले डेक तयार करा AnkiDroid निर्देशिका प्रवेश करण्यायोग्य आहे diff --git a/AnkiDroid/src/main/res/values-ms/01-core.xml b/AnkiDroid/src/main/res/values-ms/01-core.xml index 08de71bcbfdb..7cee02ed292d 100644 --- a/AnkiDroid/src/main/res/values-ms/01-core.xml +++ b/AnkiDroid/src/main/res/values-ms/01-core.xml @@ -108,7 +108,8 @@ Cari di %1$s Cap nota Buang cap nota - Semak sebutan + Enable voice playback + Disable voice playback Cipta dek Cipta dek tapisan Direktori AnkiDroid tidak dapat dicapai diff --git a/AnkiDroid/src/main/res/values-my/01-core.xml b/AnkiDroid/src/main/res/values-my/01-core.xml index 6501aeba54a2..eaf1dd608fa5 100644 --- a/AnkiDroid/src/main/res/values-my/01-core.xml +++ b/AnkiDroid/src/main/res/values-my/01-core.xml @@ -112,7 +112,8 @@ %1$s တိုးတက်လာ မှတ်သား မှတ်သားမှုဖျက် - အသံထွက်စစ် + Enable voice playback + Disable voice playback လုပ်ငန်းအသစ်ဖန်တီး ထပ်ဆင့်လုပ်ငန်းဖန်းတီး AnkiDroidအဘိဓာန်မရနိုင်ပါ diff --git a/AnkiDroid/src/main/res/values-nl/01-core.xml b/AnkiDroid/src/main/res/values-nl/01-core.xml index ec50c009e23e..c7bb9bb745b7 100644 --- a/AnkiDroid/src/main/res/values-nl/01-core.xml +++ b/AnkiDroid/src/main/res/values-nl/01-core.xml @@ -111,7 +111,8 @@ Opzoeken in %1$s Notitie markeren Notitie onmarkeren - Uitspraak controleren + Enable voice playback + Disable voice playback Leerset aanmaken Gefilterde set maken AnkiDroidmap is ontoegankelijk diff --git a/AnkiDroid/src/main/res/values-nn/01-core.xml b/AnkiDroid/src/main/res/values-nn/01-core.xml index adad8752bf65..a11788f4ed43 100644 --- a/AnkiDroid/src/main/res/values-nn/01-core.xml +++ b/AnkiDroid/src/main/res/values-nn/01-core.xml @@ -111,7 +111,8 @@ Oppslag i %1$s Marker notat Fjern markering på notat - Sjekk uttale + Enable voice playback + Disable voice playback Lag ein kortleik Lag en filtrert kortstokk AnkiDroid-mappa er utilgjengeleg diff --git a/AnkiDroid/src/main/res/values-no/01-core.xml b/AnkiDroid/src/main/res/values-no/01-core.xml index 7f0edf45f1f1..d558055b595b 100644 --- a/AnkiDroid/src/main/res/values-no/01-core.xml +++ b/AnkiDroid/src/main/res/values-no/01-core.xml @@ -111,7 +111,8 @@ Oppslag i %1$s Marker notat Fjern notatmarkering - Sjekk uttalen + Enable voice playback + Disable voice playback Lag kortstokk Lag en filtrert kortstokk AnkiDroid-mappen er utilgjengelig diff --git a/AnkiDroid/src/main/res/values-or/01-core.xml b/AnkiDroid/src/main/res/values-or/01-core.xml index 8fd64557dd6e..17a036c30b5f 100644 --- a/AnkiDroid/src/main/res/values-or/01-core.xml +++ b/AnkiDroid/src/main/res/values-or/01-core.xml @@ -111,7 +111,8 @@ %1$s ରେ ଦୃଷ୍ଟିପାତ ନୋଟ ଚିନ୍ହିତ କରନ୍ତୁ ନୋଟ ଅଣଚିନ୍ହିତ କରନ୍ତୁ - ଉଚ୍ଚାରଣ ଯାଞ୍ଚ କରନ୍ତୁ + Enable voice playback + Disable voice playback ତାସଖଣ୍ଡ ସୃଷ୍ଟି କରିବା ଶୋଧିତ ତାସଖଣ୍ଡ ସୃଷ୍ଟି କରିବା AnkiDroid directory ଅଗମ୍ୟ ଅଟେ diff --git a/AnkiDroid/src/main/res/values-pa/01-core.xml b/AnkiDroid/src/main/res/values-pa/01-core.xml index cbd46ff7844c..ac3e21c6fca7 100644 --- a/AnkiDroid/src/main/res/values-pa/01-core.xml +++ b/AnkiDroid/src/main/res/values-pa/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-pl/01-core.xml b/AnkiDroid/src/main/res/values-pl/01-core.xml index 2ed9a6dd8a9b..de382022407b 100644 --- a/AnkiDroid/src/main/res/values-pl/01-core.xml +++ b/AnkiDroid/src/main/res/values-pl/01-core.xml @@ -117,7 +117,8 @@ Wyszukiwanie w %1$s Wyróżnij notatkę Cofnij wyróżnienie notatki - Sprawdź wymowę + Enable voice playback + Disable voice playback Stwórz talię Stwórz filtrowaną talię Katalog AnkiDroid jest niedostępny diff --git a/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml b/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml index f17db378a236..a83a8dcba351 100644 --- a/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml +++ b/AnkiDroid/src/main/res/values-pt-rBR/01-core.xml @@ -111,7 +111,8 @@ Pesquisar em %1$s Marcar nota Desmarcar nota - Verificar pronúncia + Enable voice playback + Disable voice playback Criar baralho Criar baralho com filtros Diretório do AnkiDroid está inacessível diff --git a/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml b/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml index 71de095016c4..3ee6b6b5d41c 100644 --- a/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml +++ b/AnkiDroid/src/main/res/values-pt-rPT/01-core.xml @@ -111,7 +111,8 @@ Procurar em %1$s Marcar nota Desmarcar nota - Verificar a pronúncia + Enable voice playback + Disable voice playback Criar baralho Criar baralho filtrado A diretoria AnkiDroid está inacessível diff --git a/AnkiDroid/src/main/res/values-ro/01-core.xml b/AnkiDroid/src/main/res/values-ro/01-core.xml index 8e7491e4c71c..922820ad3c68 100644 --- a/AnkiDroid/src/main/res/values-ro/01-core.xml +++ b/AnkiDroid/src/main/res/values-ro/01-core.xml @@ -114,7 +114,8 @@ Căutare în %1$s Marcheaza nota Demarcheaza nota - Verifica pronunțarea + Enable voice playback + Disable voice playback Crează punte Crează punte filtrată Directorul AnkiDroid este inaccesibil diff --git a/AnkiDroid/src/main/res/values-ru/01-core.xml b/AnkiDroid/src/main/res/values-ru/01-core.xml index 8e24760971e7..b7fb07183cc4 100644 --- a/AnkiDroid/src/main/res/values-ru/01-core.xml +++ b/AnkiDroid/src/main/res/values-ru/01-core.xml @@ -117,7 +117,8 @@ Посмотреть в %1$s Отметить запись Снять отметку - Проверить произношение + Enable voice playback + Disable voice playback Создать колоду Создать фильтрованную колоду Папка AnkiDroid недоступна diff --git a/AnkiDroid/src/main/res/values-sat/01-core.xml b/AnkiDroid/src/main/res/values-sat/01-core.xml index ebfe1722a940..30a81f64679f 100644 --- a/AnkiDroid/src/main/res/values-sat/01-core.xml +++ b/AnkiDroid/src/main/res/values-sat/01-core.xml @@ -111,7 +111,8 @@ %1$s ᱨᱮ ᱧᱮᱞ ᱵᱤᱰᱟᱣ ᱢᱮ ᱠᱷᱟᱴᱚ ᱵᱤᱪᱟᱹᱨ ᱪᱤᱱᱦᱟᱹᱭ ᱢᱮ ᱠᱷᱟᱴᱚ ᱵᱤᱪᱟᱹᱨ ᱚ-ᱪᱤᱱᱦᱟᱹᱭ ᱢᱮ - ᱥᱩᱨ ᱧᱣᱞ ᱛᱟᱢ + Enable voice playback + Disable voice playback ᱱᱟᱶᱟ ᱰᱮᱠ ᱛᱮᱭᱟᱨ ᱢᱮ ᱯᱷᱤᱞᱴᱚᱨ ᱰᱮᱠ ᱛᱮᱭᱟᱨ ᱢᱮ AnkiDroid ᱩᱱᱩᱫᱩᱜ ᱫᱚ ᱵᱟᱭ ᱦᱟᱛᱟᱣ ᱫᱟᱲᱮᱟᱜ ᱠᱟᱱᱟ diff --git a/AnkiDroid/src/main/res/values-sc/01-core.xml b/AnkiDroid/src/main/res/values-sc/01-core.xml index 54543c3edafe..78b83c6f6226 100644 --- a/AnkiDroid/src/main/res/values-sc/01-core.xml +++ b/AnkiDroid/src/main/res/values-sc/01-core.xml @@ -113,7 +113,8 @@ Chirca in %1$s Marca sa nota Boga sa marcadura a sa nota - Verìfica sa pronùntzia + Enable voice playback + Disable voice playback Crea unu matzu Crea unu matzu filtradu Sa cartella de AnkiDroid no est atzessìbile diff --git a/AnkiDroid/src/main/res/values-sk/01-core.xml b/AnkiDroid/src/main/res/values-sk/01-core.xml index 3f1cdf68fd21..5389961eb775 100644 --- a/AnkiDroid/src/main/res/values-sk/01-core.xml +++ b/AnkiDroid/src/main/res/values-sk/01-core.xml @@ -117,7 +117,8 @@ Vyhľadať v %1$s Označiť poznámku Odznačiť poznámku - Skontrolovať výslovnosť + Enable voice playback + Disable voice playback Vytvoriť balíček Vytvoriť filtrovaný balíček Adresár AnkiDroid je neprístupný diff --git a/AnkiDroid/src/main/res/values-sl/01-core.xml b/AnkiDroid/src/main/res/values-sl/01-core.xml index 214f6f725835..67051c04101c 100644 --- a/AnkiDroid/src/main/res/values-sl/01-core.xml +++ b/AnkiDroid/src/main/res/values-sl/01-core.xml @@ -117,7 +117,8 @@ Poišči v %1$s Označi zapisek Odznači zapisek - Check pronunciation + Enable voice playback + Disable voice playback Ustvari komplet Ustvari filtriran komplet Slovar AnkiDroid ni na voljo diff --git a/AnkiDroid/src/main/res/values-sq/01-core.xml b/AnkiDroid/src/main/res/values-sq/01-core.xml index 2316aaf8cc50..052c85ed271c 100644 --- a/AnkiDroid/src/main/res/values-sq/01-core.xml +++ b/AnkiDroid/src/main/res/values-sq/01-core.xml @@ -111,7 +111,8 @@ Kërkoni në %1$s Shënoni shënimin Zhshënjoni shënimin - Kontrolloni shqiptimin + Enable voice playback + Disable voice playback Krijo kuvertë Krijo kuvertë të filtruar Drejtoria AnkiDroid është e paarritshme diff --git a/AnkiDroid/src/main/res/values-sr/01-core.xml b/AnkiDroid/src/main/res/values-sr/01-core.xml index f3c7fb232d0c..1ef2159b8e40 100644 --- a/AnkiDroid/src/main/res/values-sr/01-core.xml +++ b/AnkiDroid/src/main/res/values-sr/01-core.xml @@ -114,7 +114,8 @@ Потражи у %1$s Означи белешку Уклони ознаку белешке - Провери изговор + Enable voice playback + Disable voice playback Направи шпил Направи филтриран шпил Недоступан каталог AnkiDroid diff --git a/AnkiDroid/src/main/res/values-ss/01-core.xml b/AnkiDroid/src/main/res/values-ss/01-core.xml index d9833f3293b9..9a55242b2de5 100644 --- a/AnkiDroid/src/main/res/values-ss/01-core.xml +++ b/AnkiDroid/src/main/res/values-ss/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-sv/01-core.xml b/AnkiDroid/src/main/res/values-sv/01-core.xml index 21c9a7d9165c..6b369cac2b99 100644 --- a/AnkiDroid/src/main/res/values-sv/01-core.xml +++ b/AnkiDroid/src/main/res/values-sv/01-core.xml @@ -111,7 +111,8 @@ Sökning i %1$s Markera not Avmarkera not - Kontrollera uttal + Enable voice playback + Disable voice playback Skapa kortlek Skapa filtrerad kortlek AnkiDroid-mappen är inte tillgänglig diff --git a/AnkiDroid/src/main/res/values-sw/01-core.xml b/AnkiDroid/src/main/res/values-sw/01-core.xml index d9833f3293b9..9a55242b2de5 100644 --- a/AnkiDroid/src/main/res/values-sw/01-core.xml +++ b/AnkiDroid/src/main/res/values-sw/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-ta/01-core.xml b/AnkiDroid/src/main/res/values-ta/01-core.xml index cfeb70485c02..157d32aa9605 100644 --- a/AnkiDroid/src/main/res/values-ta/01-core.xml +++ b/AnkiDroid/src/main/res/values-ta/01-core.xml @@ -111,7 +111,8 @@ இங்கே பாருங்கள் %1$s குறிப்பு குறிக்கவும் குறிப்பு குறிக்கப்படாது - உச்சரிப்பை சரிபார் + Enable voice playback + Disable voice playback டெக் உருவாக்கவும் வடிகட்டப்பட்ட டெக் உருவாக்கவும் AnkiDroid அடைவு அணுகக்கூடியதாக diff --git a/AnkiDroid/src/main/res/values-te/01-core.xml b/AnkiDroid/src/main/res/values-te/01-core.xml index 033a6ac93eef..7dff0f04c17b 100644 --- a/AnkiDroid/src/main/res/values-te/01-core.xml +++ b/AnkiDroid/src/main/res/values-te/01-core.xml @@ -111,7 +111,8 @@ లో చూడండి%1$s గమనికను గుర్తు పెట్టుకోండి గమనిక నుండి గుర్తు తీసివేయండి - ఉచ్చారణను తనిఖీ చేయండి + Enable voice playback + Disable voice playback ఒక డెక్ సృష్టించండి ఫిల్టర్ డెక్ను సృష్టించండి AnkiDroid డైరెక్టరీ అందుబాటులో లేదు diff --git a/AnkiDroid/src/main/res/values-tg/01-core.xml b/AnkiDroid/src/main/res/values-tg/01-core.xml index edbc8e78e659..698135dd3610 100644 --- a/AnkiDroid/src/main/res/values-tg/01-core.xml +++ b/AnkiDroid/src/main/res/values-tg/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-tgl/01-core.xml b/AnkiDroid/src/main/res/values-tgl/01-core.xml index 74da823ad2f3..1bf7d2be2de5 100644 --- a/AnkiDroid/src/main/res/values-tgl/01-core.xml +++ b/AnkiDroid/src/main/res/values-tgl/01-core.xml @@ -111,7 +111,8 @@ Hanapin sa %1$s Markahan ang paalala Tangalin ang marka ng paalala - Check pronunciation + Enable voice playback + Disable voice playback Gumawa ng deck Gumawa ng salang deck Hindi ma-access ang talahanapan ng AnkiDroid diff --git a/AnkiDroid/src/main/res/values-th/01-core.xml b/AnkiDroid/src/main/res/values-th/01-core.xml index 9422e4dc07b6..ffcd2980584b 100644 --- a/AnkiDroid/src/main/res/values-th/01-core.xml +++ b/AnkiDroid/src/main/res/values-th/01-core.xml @@ -108,7 +108,8 @@ ค้นหาใน %1$s ทำเครื่องหมายโน้ต ยกเลิกการทำเครื่องหมายโน้ต - ตรวจสอบวิธีการออกเสียง + Enable voice playback + Disable voice playback สร้างกองใหม่ สร้าง สำรับแบบกรอง เข้าถึงที่เก็บข้อมูล AnkiDroid ไม่ได้ diff --git a/AnkiDroid/src/main/res/values-ti/01-core.xml b/AnkiDroid/src/main/res/values-ti/01-core.xml index 9a061665baf8..b534d57623c4 100644 --- a/AnkiDroid/src/main/res/values-ti/01-core.xml +++ b/AnkiDroid/src/main/res/values-ti/01-core.xml @@ -111,7 +111,8 @@ ኣብ %1$s ርአ ጽሑፍ ምልክት ግበረሉ ምልክት ዝገበርካሉ ጽሑፍ ምልክቱ ደምስስ - Check pronunciation + Enable voice playback + Disable voice playback ሓዲሽ ባይታ ፍጠር ዝፍለ ባይታ ፍጠር ዲክሽነርይ AnkiDroid ክእቶ ኣይክእልን ኢዩ። diff --git a/AnkiDroid/src/main/res/values-tn/01-core.xml b/AnkiDroid/src/main/res/values-tn/01-core.xml index d9833f3293b9..9a55242b2de5 100644 --- a/AnkiDroid/src/main/res/values-tn/01-core.xml +++ b/AnkiDroid/src/main/res/values-tn/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-tr/01-core.xml b/AnkiDroid/src/main/res/values-tr/01-core.xml index 4943934b8643..49b300d476fc 100644 --- a/AnkiDroid/src/main/res/values-tr/01-core.xml +++ b/AnkiDroid/src/main/res/values-tr/01-core.xml @@ -111,7 +111,8 @@ %1$s\'de Ara Notu işaretle İşareti kaldır - Telaffuzu kontrol et + Enable voice playback + Disable voice playback Deste oluştur Filtreli deste oluştur AnkiDroid dizinine ulaşılamıyor diff --git a/AnkiDroid/src/main/res/values-ts/01-core.xml b/AnkiDroid/src/main/res/values-ts/01-core.xml index d9833f3293b9..9a55242b2de5 100644 --- a/AnkiDroid/src/main/res/values-ts/01-core.xml +++ b/AnkiDroid/src/main/res/values-ts/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-tt/01-core.xml b/AnkiDroid/src/main/res/values-tt/01-core.xml index 4c61286b5ae8..1d9329b47cfd 100644 --- a/AnkiDroid/src/main/res/values-tt/01-core.xml +++ b/AnkiDroid/src/main/res/values-tt/01-core.xml @@ -108,7 +108,8 @@ %1$sдә карарга Язуны билгеләү Билгеләүне бетерергә - Әйтелешне тикшерү + Enable voice playback + Disable voice playback Колода ясау Фильтрлы колода ясау AnkiDroid папкасына рөхсәт юк diff --git a/AnkiDroid/src/main/res/values-uk/01-core.xml b/AnkiDroid/src/main/res/values-uk/01-core.xml index 3f146b6159d7..84c77e513656 100644 --- a/AnkiDroid/src/main/res/values-uk/01-core.xml +++ b/AnkiDroid/src/main/res/values-uk/01-core.xml @@ -117,7 +117,8 @@ Пошук у %1$s Позначити запис Зняти позначку запису - Перевірити вимову + Enable voice playback + Disable voice playback Створити колоду Створити фільтровану колоду Папка AnkiDroid недоступна diff --git a/AnkiDroid/src/main/res/values-ur/01-core.xml b/AnkiDroid/src/main/res/values-ur/01-core.xml index f77c673136f5..a615f078a49a 100644 --- a/AnkiDroid/src/main/res/values-ur/01-core.xml +++ b/AnkiDroid/src/main/res/values-ur/01-core.xml @@ -111,7 +111,8 @@ %1$s میں تلاش کریں نوٹ کو نشان زد کریں نوٹ بے نشان کریں - تلفظ چیک کریں + Enable voice playback + Disable voice playback ڈیک بنائیں فلٹر شدہ ڈیک بنائیں آنکی ڈیرائڈ ڈائریکٹری ناقابل رسائی ہے diff --git a/AnkiDroid/src/main/res/values-uz/01-core.xml b/AnkiDroid/src/main/res/values-uz/01-core.xml index 85a6ec665bb4..a959b5bf470b 100644 --- a/AnkiDroid/src/main/res/values-uz/01-core.xml +++ b/AnkiDroid/src/main/res/values-uz/01-core.xml @@ -111,7 +111,8 @@ %1$s dan izlab ko\'rish Qaydni belgilash Qayddan belgini olib tashlash - Talaffuzni tekshirish + Enable voice playback + Disable voice playback Paluba yaratish Siljiydigan paluba yaratish AnkiDroid katalogi mavjud emas diff --git a/AnkiDroid/src/main/res/values-ve/01-core.xml b/AnkiDroid/src/main/res/values-ve/01-core.xml index d9833f3293b9..9a55242b2de5 100644 --- a/AnkiDroid/src/main/res/values-ve/01-core.xml +++ b/AnkiDroid/src/main/res/values-ve/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-vi/01-core.xml b/AnkiDroid/src/main/res/values-vi/01-core.xml index fce3e46075b4..8362e7b9e4fa 100644 --- a/AnkiDroid/src/main/res/values-vi/01-core.xml +++ b/AnkiDroid/src/main/res/values-vi/01-core.xml @@ -108,7 +108,8 @@ Tra cứu trong %1$s Đánh dấu ghi chú Bỏ đánh dấu ghi chú - Kiểm tra phát âm + Enable voice playback + Disable voice playback Tạo bộ thẻ Tạo bộ thẻ đã lọc Không thể truy cập thư mục AnkiDroid diff --git a/AnkiDroid/src/main/res/values-wo/01-core.xml b/AnkiDroid/src/main/res/values-wo/01-core.xml index 05a12d6e13f3..46df6df49856 100644 --- a/AnkiDroid/src/main/res/values-wo/01-core.xml +++ b/AnkiDroid/src/main/res/values-wo/01-core.xml @@ -108,7 +108,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-xh/01-core.xml b/AnkiDroid/src/main/res/values-xh/01-core.xml index d9833f3293b9..9a55242b2de5 100644 --- a/AnkiDroid/src/main/res/values-xh/01-core.xml +++ b/AnkiDroid/src/main/res/values-xh/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-yue/01-core.xml b/AnkiDroid/src/main/res/values-yue/01-core.xml index b5aa14e7bb57..679ea19324bb 100644 --- a/AnkiDroid/src/main/res/values-yue/01-core.xml +++ b/AnkiDroid/src/main/res/values-yue/01-core.xml @@ -108,7 +108,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible diff --git a/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml b/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml index 99909de3f56a..cd1323543def 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml @@ -101,14 +101,15 @@ 暂停 删除笔记 旗标 - Rename flags + 重命名标记 为卡片设置旗标 编辑标签​​​​​ 确定要删除此笔记及生成的卡片?\n%s 在%1$s中查找 标记笔记 取消标记 - 检查发音 + Enable voice playback + Disable voice playback 创建牌组 创建筛选牌组 无法访问AnkiDroid目录 diff --git a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml index 64cd1ff0aabf..659d5babc98c 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml @@ -251,5 +251,5 @@ 系统 WebView 已过时。有些功能将无法正常工作。请更新它。\n\n已安装版本: %1$d\n所需最低版本: %2$d - Confirm all changes before saving + 保存前确认所有更改 diff --git a/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml b/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml index cf1f0018af19..033a7769fb69 100644 --- a/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml +++ b/AnkiDroid/src/main/res/values-zh-rTW/01-core.xml @@ -109,7 +109,8 @@ 在%1$s中查詢 標記筆記 取消標記筆記 - 檢查發音 + Enable voice playback + Disable voice playback 建立牌組 新增篩選牌組 無法存取 AnkiDroid 目錄 diff --git a/AnkiDroid/src/main/res/values-zu/01-core.xml b/AnkiDroid/src/main/res/values-zu/01-core.xml index d9833f3293b9..9a55242b2de5 100644 --- a/AnkiDroid/src/main/res/values-zu/01-core.xml +++ b/AnkiDroid/src/main/res/values-zu/01-core.xml @@ -111,7 +111,8 @@ Lookup in %1$s Mark note Unmark note - Check pronunciation + Enable voice playback + Disable voice playback Create deck Create filtered deck AnkiDroid directory is inaccessible From 9bda35fa1ae641dcc76a1029802e35db91f7d9e6 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Tue, 18 Jun 2024 14:14:00 -0500 Subject: [PATCH 095/138] feat(ci): apk size comparison workflow --- .github/workflows/compare_apk_size.yml | 116 +++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 .github/workflows/compare_apk_size.yml diff --git a/.github/workflows/compare_apk_size.yml b/.github/workflows/compare_apk_size.yml new file mode 100644 index 000000000000..40409520cd0f --- /dev/null +++ b/.github/workflows/compare_apk_size.yml @@ -0,0 +1,116 @@ +name: APK Size Comparison + +on: + workflow_dispatch: + inputs: + prNumber: + description: "Number of PR to calculate sizes for" + required: true + type: number + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + + +permissions: + contents: read + pull-requests: write + + +jobs: + sizeCheck: + name: APK Size Check + timeout-minutes: 30 + runs-on: ubuntu-latest + env: + # could be better, '/home/runner' should be '~/' but neither that nor '$HOME' worked + STOREFILEDIR: /home/runner/src + STOREFILE: android-keystore + STOREPASS: testpass + KEYPASS: testpass + KEYALIAS: nrkeystorealias + steps: + - name: Configure JDK + uses: actions/setup-java@v4 + with: + distribution: "temurin" + java-version: "21" + + - name: Test Credential Prep + run: | + echo "KSTOREPWD=$STOREPASS" >> $GITHUB_ENV + echo "KEYPWD=$KEYPASS" >> $GITHUB_ENV + mkdir $STOREFILEDIR + cd $STOREFILEDIR + echo y | keytool -genkeypair -dname "cn=AnkiDroid, ou=ankidroid, o=AnkiDroid, c=US" -alias $KEYALIAS -keypass $KEYPASS -keystore "$STOREFILE" -storepass $STOREPASS -keyalg RSA -validity 20000 + shell: bash + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v3 + timeout-minutes: 5 + with: + cache-read-only: true + gradle-home-cache-cleanup: true + + - name: Checkout PR + uses: actions/checkout@v4 + with: + fetch-depth: 1 + ref: 'refs/pull/${{ github.event.inputs.prNumber }}/head' + + - name: Assemble PR APK + # This makes sure we fetch gradle network resources with a retry + uses: nick-invision/retry@v3 + with: + timeout_minutes: 10 + retry_wait_seconds: 60 + max_attempts: 3 + command: ./gradlew :AnkiDroid:assemblePlayRelease --daemon + + - name: Get PR APK size + run: echo NEWSIZE=`ls -lrt AnkiDroid/build/outputs/apk/play/release/AnkiDroid-play-arm64-v8a-release.apk | awk '{print $5}'` >> $GITHUB_ENV + + - uses: actions/checkout@v4 + with: + ref: main + fetch-depth: 1 + + - name: Assemble Baseline APK + # This makes sure we fetch gradle network resources with a retry + uses: nick-invision/retry@v3 + with: + timeout_minutes: 10 + retry_wait_seconds: 60 + max_attempts: 3 + command: ./gradlew :AnkiDroid:assemblePlayRelease --daemon + + - name: Get Baseline APK size + run: echo OLDSIZE=`ls -lrt AnkiDroid/build/outputs/apk/play/release/AnkiDroid-play-arm64-v8a-release.apk | awk '{print $5}'` >> $GITHUB_ENV + + - name: Post comment + uses: actions/github-script@v7 + with: + script: | + var inputs = ${{ toJSON(inputs) }} + let prNumber = inputs['prNumber']; + + async function getPullRequest() { + return await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + }); + } + const pullRequestData = await getPullRequest(); + + async function addComment(prNumber, oldSize, newSize) { + return await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: `Old APK size: ${oldSize} + New APK size: ${newSize}` + }) + } + await addComment(prNumber, process.env.OLDSIZE, process.env.NEWSIZE); From 40610eee2faab6ed7bfc54b35f05ef29eb6fae6f Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Sat, 15 Jun 2024 19:41:02 +0100 Subject: [PATCH 096/138] refactor: prep for multiple BrowserColumns * Moves save/load into CardBrowserColumn * Use the enum values, rather than the indices Prep for Issue 11889 --- .../main/java/com/ichi2/anki/CardBrowser.kt | 34 +++++++++--------- .../ichi2/anki/browser/CardBrowserColumn.kt | 31 ++++++++++++++++ .../anki/browser/CardBrowserViewModel.kt | 35 ++++++++++--------- .../com/ichi2/async/CollectionOperations.kt | 7 ++-- .../anki/browser/CardBrowserViewModelTest.kt | 28 ++++++++------- 5 files changed, 86 insertions(+), 49 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt index 138b9de3b8e6..7a1ec3a210b4 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt @@ -348,8 +348,8 @@ open class CardBrowser : val sflRelativeFontSize = preferences.getInt("relativeCardBrowserFontSize", DEFAULT_FONT_SIZE_RATIO) val columnsContent = arrayOf( - COLUMN1_KEYS[viewModel.column1Index], - COLUMN2_KEYS[viewModel.column2Index] + viewModel.column1, + viewModel.column2 ) // make a new list adapter mapping the data in mCards to column1 and column2 of R.layout.card_item_browser cardsAdapter = MultiColumnListAdapter( @@ -407,10 +407,10 @@ open class CardBrowser : } } fun onSelectedRowsChanged(rows: Set) = onSelectionChanged() - fun onColumnIndex1Changed(index: Int) = - cardsAdapter.updateMapping { it[0] = COLUMN1_KEYS[index] } - fun onColumnIndex2Changed(index: Int) = - cardsAdapter.updateMapping { it[1] = COLUMN2_KEYS[index] } + fun onColumn1Changed(column: CardBrowserColumn) = + cardsAdapter.updateMapping { it[0] = column } + fun onColumn2Changed(column: CardBrowserColumn) = + cardsAdapter.updateMapping { it[1] = column } fun onFilterQueryChanged(filterQuery: String) { // setQuery before expand does not set the view's value searchItem!!.expandActionView() @@ -469,8 +469,8 @@ open class CardBrowser : viewModel.flowOfIsTruncated.launchCollectionInLifecycleScope(::onIsTruncatedChanged) viewModel.flowOfSearchQueryExpanded.launchCollectionInLifecycleScope(::onSearchQueryExpanded) viewModel.flowOfSelectedRows.launchCollectionInLifecycleScope(::onSelectedRowsChanged) - viewModel.flowOfColumnIndex1.launchCollectionInLifecycleScope(::onColumnIndex1Changed) - viewModel.flowOfColumnIndex2.launchCollectionInLifecycleScope(::onColumnIndex2Changed) + viewModel.flowOfColumn1.launchCollectionInLifecycleScope(::onColumn1Changed) + viewModel.flowOfColumn2.launchCollectionInLifecycleScope(::onColumn2Changed) viewModel.flowOfFilterQuery.launchCollectionInLifecycleScope(::onFilterQueryChanged) viewModel.flowOfDeckId.launchCollectionInLifecycleScope(::onDeckIdChanged) viewModel.flowOfCanSearch.launchCollectionInLifecycleScope(::onCanSaveChanged) @@ -496,9 +496,9 @@ open class CardBrowser : setDropDownViewResource(R.layout.spinner_custom_layout) } onItemSelectedListener = BasicItemSelectedListener { pos, _ -> - viewModel.setColumn1Index(pos) + viewModel.setColumn1(COLUMN1_KEYS[pos]) } - setSelection(viewModel.column1Index) + setSelection(COLUMN1_KEYS.indexOf(viewModel.column1)) } // Setup the column 2 heading as a spinner so that users can easily change the column type findViewById(R.id.browser_column2_spinner).apply { @@ -512,9 +512,9 @@ open class CardBrowser : } // Create a new list adapter with updated column map any time the user changes the column onItemSelectedListener = BasicItemSelectedListener { pos, _ -> - viewModel.setColumn2Index(pos) + viewModel.setColumn2(COLUMN2_KEYS[pos]) } - setSelection(viewModel.column2Index) + setSelection(COLUMN2_KEYS.indexOf(viewModel.column2)) } cardsListView.setOnItemClickListener { _: AdapterView<*>?, view: View?, position: Int, _: Long -> @@ -1482,7 +1482,7 @@ open class CardBrowser : .mapNotNull { cid -> idToPos[cid] } .filterNot { pos -> pos >= viewModel.rowCount } .map { pos -> viewModel.getRowAtPosition(pos) } - .forEach { it.load(true, viewModel.column1Index, viewModel.column2Index) } + .forEach { it.load(true, viewModel.column1, viewModel.column2) } updateList() } @@ -1672,8 +1672,8 @@ open class CardBrowser : cards, firstVisibleItem, visibleItemCount, - viewModel.column1Index, - viewModel.column2Index + viewModel.column1, + viewModel.column2 ) { // Note: This is called every time a card is rendered. // It blocks the long-click callback while the task is running, so usage of the task should be minimized @@ -1982,13 +1982,13 @@ open class CardBrowser : /** pre compute the note and question/answer. It can safely * be called twice without doing extra work. */ - fun load(reload: Boolean, column1Index: Int, column2Index: Int) { + fun load(reload: Boolean, column1: CardBrowserColumn, column2: CardBrowserColumn) { if (reload) { reload() } card.note(col) // First column can not be the answer. If it were to change, this code should also be changed. - if (COLUMN1_KEYS[column1Index] == CardBrowserColumn.QUESTION || arrayOf(CardBrowserColumn.QUESTION, CardBrowserColumn.ANSWER).contains(COLUMN2_KEYS[column2Index])) { + if (column1 == CardBrowserColumn.QUESTION || arrayOf(CardBrowserColumn.QUESTION, CardBrowserColumn.ANSWER).contains(column2)) { updateSearchItemQA() } isLoaded = true diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt index ed0e078a4994..7b0c609944c8 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt @@ -16,12 +16,15 @@ package com.ichi2.anki.browser +import android.content.SharedPreferences +import androidx.core.content.edit import anki.search.BrowserColumns import com.ichi2.anki.CardBrowser import com.ichi2.anki.R import com.ichi2.anki.browser.CardBrowserViewModel.Companion.DISPLAY_COLUMN_1_KEY import com.ichi2.anki.browser.CardBrowserViewModel.Companion.DISPLAY_COLUMN_2_KEY import net.ankiweb.rsdroid.Backend +import timber.log.Timber /** * A column available in the [browser][CardBrowser] @@ -120,6 +123,34 @@ enum class CardBrowserColumn(val ankiColumnKey: String) { // list of available keys in mCards corresponding to the column names in R.array.browser_column2_headings. // Note: the last 6 are currently hidden val COLUMN2_KEYS = arrayOf(ANSWER, CARD, DECK, NOTE_TYPE, QUESTION, TAGS, LAPSES, REVIEWS, INTERVAL, EASE, DUE, CHANGED, CREATED, EDITED) + + fun SharedPreferences.loadBrowserColumn(index: Int): CardBrowserColumn { + return when (index) { + 0 -> COLUMN1_KEYS[getInt(DISPLAY_COLUMN_1_KEY, 0)] + 1 -> COLUMN2_KEYS[getInt(DISPLAY_COLUMN_2_KEY, 0)] + else -> { + Timber.w("Unexpected column access: %d", index) + QUESTION + } + } + } + + fun save(prefs: SharedPreferences, columnIndex: Int, value: CardBrowserColumn) { + if (columnIndex != 0 && columnIndex != 1) return + val (key, array) = when (columnIndex) { + 0 -> Pair(DISPLAY_COLUMN_1_KEY, COLUMN1_KEYS) + 1 -> Pair(DISPLAY_COLUMN_2_KEY, COLUMN2_KEYS) + else -> throw IllegalStateException() + } + + Timber.i("updating '%s' to '%s'", key, value) + val index = array.indexOf(value) + if (index == -1) { + Timber.w("illegal value: %s", value) + return + } + prefs.edit { putInt(key, index) } + } } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index 91114de5ecdd..e568a5b11302 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -32,6 +32,7 @@ import com.ichi2.anki.CollectionManager.withCol import com.ichi2.anki.DeckSpinnerSelection.Companion.ALL_DECKS_ID import com.ichi2.anki.Flag import com.ichi2.anki.PreviewerDestination +import com.ichi2.anki.browser.CardBrowserColumn.Companion.loadBrowserColumn import com.ichi2.anki.export.ExportDialogFragment.* import com.ichi2.anki.launchCatchingIO import com.ichi2.anki.model.CardStateFilter @@ -134,10 +135,10 @@ class CardBrowserViewModel( private val reverseDirectionFlow = MutableStateFlow(ReverseDirection(orderAsc = false)) val orderAsc get() = reverseDirectionFlow.value.orderAsc - val flowOfColumnIndex1 = MutableStateFlow(sharedPrefs().getInt(DISPLAY_COLUMN_1_KEY, 0)) - val flowOfColumnIndex2 = MutableStateFlow(sharedPrefs().getInt(DISPLAY_COLUMN_2_KEY, 0)) - val column1Index get() = flowOfColumnIndex1.value - val column2Index get() = flowOfColumnIndex2.value + val flowOfColumn1 = MutableStateFlow(sharedPrefs().loadBrowserColumn(0)) + val flowOfColumn2 = MutableStateFlow(sharedPrefs().loadBrowserColumn(1)) + val column1 get() = flowOfColumn1.value + val column2 get() = flowOfColumn2.value val flowOfSearchQueryExpanded = MutableStateFlow(false) @@ -273,20 +274,14 @@ class CardBrowserViewModel( null -> {} } - flowOfColumnIndex1 + flowOfColumn1 .ignoreValuesFromViewModelLaunch() - .onEach { index -> - Timber.d("updating %s", DISPLAY_COLUMN_1_KEY) - sharedPrefs().edit { putInt(DISPLAY_COLUMN_1_KEY, index) } - } + .onEach { column -> CardBrowserColumn.save(sharedPrefs(), columnIndex = 0, value = column) } .launchIn(viewModelScope) - flowOfColumnIndex2 + flowOfColumn2 .ignoreValuesFromViewModelLaunch() - .onEach { index -> - Timber.d("updating %s", DISPLAY_COLUMN_2_KEY) - sharedPrefs().edit { putInt(DISPLAY_COLUMN_2_KEY, index) } - } + .onEach { column -> CardBrowserColumn.save(sharedPrefs(), columnIndex = 1, value = column) } .launchIn(viewModelScope) performSearchFlow.onEach { @@ -466,9 +461,15 @@ class CardBrowserViewModel( } } - fun setColumn1Index(value: Int) = flowOfColumnIndex1.update { value } + fun setColumn1(value: CardBrowserColumn) { + Timber.d("updating column 1 to %s", value) + flowOfColumn1.update { value } + } - fun setColumn2Index(value: Int) = flowOfColumnIndex2.update { value } + fun setColumn2(value: CardBrowserColumn) { + Timber.d("updating column 2 to %s", value) + flowOfColumn2.update { value } + } /** * Toggles the 'suspend' state of the selected cards @@ -749,7 +750,7 @@ class CardBrowserViewModel( val cardsToRender = min((numCardsToRender ?: 0), cards.size) for (i in 0 until cardsToRender) { ensureActive() - cards[i].load(false, column1Index, column2Index) + cards[i].load(false, column1, column2) } ensureActive() this@CardBrowserViewModel.cards.replaceWith(cards) diff --git a/AnkiDroid/src/main/java/com/ichi2/async/CollectionOperations.kt b/AnkiDroid/src/main/java/com/ichi2/async/CollectionOperations.kt index e6309156e33f..58af41b7fa23 100644 --- a/AnkiDroid/src/main/java/com/ichi2/async/CollectionOperations.kt +++ b/AnkiDroid/src/main/java/com/ichi2/async/CollectionOperations.kt @@ -17,6 +17,7 @@ package com.ichi2.async import com.ichi2.anki.* +import com.ichi2.anki.browser.CardBrowserColumn import com.ichi2.libanki.* import com.ichi2.libanki.Collection import kotlinx.coroutines.Dispatchers @@ -64,8 +65,8 @@ suspend fun renderBrowserQA( cards: List, startPos: Int, n: Int, - column1Index: Int, - column2Index: Int, + column1: CardBrowserColumn, + column2: CardBrowserColumn, onProgressUpdate: (Int) -> Unit ): Pair, MutableList> = withContext(Dispatchers.IO) { Timber.d("doInBackgroundRenderBrowserQA") @@ -104,7 +105,7 @@ suspend fun renderBrowserQA( continue } // Update item - card.load(false, column1Index, column2Index) + card.load(false, column1, column2) val progress = i.toFloat() / n * 100 withContext(Dispatchers.Main) { onProgressUpdate(progress.toInt()) } } diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index 5ae2ae7e797c..4bb09a1d2765 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -25,6 +25,10 @@ import com.ichi2.anki.CollectionManager import com.ichi2.anki.DeckSpinnerSelection import com.ichi2.anki.Flag import com.ichi2.anki.NoteEditor +import com.ichi2.anki.browser.CardBrowserColumn.ANSWER +import com.ichi2.anki.browser.CardBrowserColumn.CARD +import com.ichi2.anki.browser.CardBrowserColumn.QUESTION +import com.ichi2.anki.browser.CardBrowserColumn.SFLD import com.ichi2.anki.browser.CardBrowserLaunchOptions.DeepLink import com.ichi2.anki.browser.CardBrowserLaunchOptions.SystemContextMenu import com.ichi2.anki.export.ExportDialogFragment @@ -313,36 +317,36 @@ class CardBrowserViewModelTest : JvmTest() { @Test fun `changing column index 1`() = runViewModelTest { - flowOfColumnIndex1.test { + flowOfColumn1.test { ignoreEventsDuringViewModelInit() - assertThat("default column1Index value", column1Index, equalTo(0)) + assertThat("default column1 value", column1, equalTo(QUESTION)) - setColumn1Index(1) + setColumn1(SFLD) - assertThat("flowOfColumnIndex1", awaitItem(), equalTo(1)) - assertThat("column1Index", column1Index, equalTo(1)) + assertThat("flowOfColumn1", awaitItem(), equalTo(SFLD)) + assertThat("column1", column1, equalTo(SFLD)) // expect no change if the value is selected again - setColumn1Index(1) + setColumn1(SFLD) expectNoEvents() } } @Test fun `changing column index 2`() = runViewModelTest { - flowOfColumnIndex2.test { + flowOfColumn2.test { ignoreEventsDuringViewModelInit() - assertThat("default column2Index value", column2Index, equalTo(0)) + assertThat("default column2Index value", column2, equalTo(ANSWER)) - setColumn2Index(1) + setColumn2(CARD) - assertThat("flowOfColumnIndex2", awaitItem(), equalTo(1)) - assertThat("column2Index", column2Index, equalTo(1)) + assertThat("flowOfColumnIndex2", awaitItem(), equalTo(CARD)) + assertThat("column2Index", column2, equalTo(CARD)) // expect no change if the value is selected again - setColumn2Index(1) + setColumn2(CARD) expectNoEvents() } } From 68151e686cf40906a67513bcfcdc86b9672feb9a Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Sat, 15 Jun 2024 21:43:19 +0100 Subject: [PATCH 097/138] feat(preferences): improve browser columns Breaking! Updates the default columns from: * QUESTION, ANSWER to * Cards: [Sort Field, Card Type, Due, Deck] * Notes: [Sort Field, Note Type, Card Type/Type Count, Tags] ---- improvements: * Support different columns for CARDS and NOTES mode * Support more than 2 columns (not yet usable in the UI) deprecates + upgrades shared prefs: * "cardBrowserColumn1" - index into `COLUMN1_KEYS` * "cardBrowserColumn2" - index into `COLUMN2_KEYS` now (shared prefs): * "activeCols" -> `|` separated list of column keys * "activeNoteCols" -> `|` separated list of column keys Prep for Issue 11889 --- .../anki/browser/BrowserColumnCollection.kt | 97 +++++++++++++++++ .../ichi2/anki/browser/CardBrowserColumn.kt | 42 ++------ .../anki/browser/CardBrowserViewModel.kt | 24 +++-- .../servicelayer/PreferenceUpgradeService.kt | 69 ++++++++++++ .../java/com/ichi2/anki/CardBrowserTest.kt | 96 ++++++++++++++--- .../browser/BrowserColumnCollectionTest.kt | 100 ++++++++++++++++++ .../anki/browser/CardBrowserViewModelTest.kt | 61 ++++++++--- 7 files changed, 422 insertions(+), 67 deletions(-) create mode 100644 AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt create mode 100644 AnkiDroid/src/test/java/com/ichi2/anki/browser/BrowserColumnCollectionTest.kt diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt new file mode 100644 index 000000000000..0639604cbb07 --- /dev/null +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2024 David Allison + * + * 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 . + */ + +package com.ichi2.anki.browser + +import android.content.SharedPreferences +import androidx.annotation.CheckResult +import androidx.core.content.edit +import com.ichi2.anki.CardBrowser +import com.ichi2.anki.model.CardsOrNotes +import com.ichi2.anki.model.CardsOrNotes.CARDS +import com.ichi2.anki.model.CardsOrNotes.NOTES +import com.ichi2.libanki.BrowserConfig +import com.ichi2.libanki.BrowserConfig.ACTIVE_CARD_COLUMNS_KEY +import com.ichi2.libanki.BrowserConfig.ACTIVE_NOTE_COLUMNS_KEY +import com.ichi2.libanki.BrowserDefaults +import net.ankiweb.rsdroid.Backend +import timber.log.Timber + +/** + * A collection of columns available in the [browser][CardBrowser] + * + * These are stored in [SharedPreferences] under either: + * * [ACTIVE_CARD_COLUMNS_KEY] + * * [ACTIVE_NOTE_COLUMNS_KEY] + * + * @see Backend.setActiveBrowserColumns + * @see BrowserConfig.activeColumnsKey + */ +class BrowserColumnCollection(val columns: List) { + val count = columns.size + operator fun get(index: Int) = columns[index] + + companion object { + private const val SEPARATOR_CHAR = '|' + + @CheckResult + fun load(prefs: SharedPreferences, mode: CardsOrNotes): BrowserColumnCollection { + val key = mode.toPreferenceKey() + val columns = try { + val value = prefs.getString(key, mode.defaultColumns())!! + value.split(SEPARATOR_CHAR).map { CardBrowserColumn.fromColumnKey(it) } + } catch (e: Exception) { + Timber.w(e, "error loading columns, returning default") + val value = mode.defaultColumns() + value.split(SEPARATOR_CHAR).map { CardBrowserColumn.fromColumnKey(it) } + } + return BrowserColumnCollection(columns) + } + + /** + * @param block Update the column list here. `null` meaning 'none' + */ + fun update( + prefs: SharedPreferences, + mode: CardsOrNotes, + block: (MutableList) -> Boolean + ) { + val valuesToUpdate: MutableList = load(prefs, mode).columns.toMutableList() + if (!block(valuesToUpdate)) { + Timber.d("no changes requested") + return + } + // as in AnkiMobile, this converts: [QUESTION, NONE, TAGS] into [QUESTION, TAGS] + val updatedValues = valuesToUpdate.filterNotNull() + save(prefs, mode, BrowserColumnCollection(updatedValues)) + } + + fun save(prefs: SharedPreferences, mode: CardsOrNotes, value: BrowserColumnCollection) { + val key = mode.toPreferenceKey() + val preferenceValue = value.columns + .joinToString(separator = SEPARATOR_CHAR.toString()) { it.ankiColumnKey } + Timber.d("updating '%s' to '%s'", key, preferenceValue) + prefs.edit { putString(key, preferenceValue) } + } + + private fun CardsOrNotes.toPreferenceKey() = + BrowserConfig.activeColumnsKey(isNotesMode = this == NOTES) + + private fun CardsOrNotes.defaultColumns() = + (if (this == CARDS) BrowserDefaults.CARD_COLUMNS else BrowserDefaults.NOTE_COLUMNS) + .joinToString(separator = SEPARATOR_CHAR.toString()) + } +} diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt index 7b0c609944c8..f687951b3e0d 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt @@ -16,21 +16,16 @@ package com.ichi2.anki.browser -import android.content.SharedPreferences -import androidx.core.content.edit import anki.search.BrowserColumns import com.ichi2.anki.CardBrowser import com.ichi2.anki.R -import com.ichi2.anki.browser.CardBrowserViewModel.Companion.DISPLAY_COLUMN_1_KEY -import com.ichi2.anki.browser.CardBrowserViewModel.Companion.DISPLAY_COLUMN_2_KEY import net.ankiweb.rsdroid.Backend -import timber.log.Timber /** * A column available in the [browser][CardBrowser] * - * @see COLUMN1_KEYS: from preference [DISPLAY_COLUMN_1_KEY] to [R.array.browser_column1_headings] - * @see COLUMN2_KEYS: from preference [DISPLAY_COLUMN_2_KEY] to [R.array.browser_column2_headings] + * @see COLUMN1_KEYS: maps to [R.array.browser_column1_headings] + * @see COLUMN2_KEYS: maps to [R.array.browser_column2_headings] * @see CardBrowser.CardCache.getColumnHeaderText - how columns are rendered * * @param ankiColumnKey The key used in [Backend.setActiveBrowserColumns] @@ -124,35 +119,12 @@ enum class CardBrowserColumn(val ankiColumnKey: String) { // Note: the last 6 are currently hidden val COLUMN2_KEYS = arrayOf(ANSWER, CARD, DECK, NOTE_TYPE, QUESTION, TAGS, LAPSES, REVIEWS, INTERVAL, EASE, DUE, CHANGED, CREATED, EDITED) - fun SharedPreferences.loadBrowserColumn(index: Int): CardBrowserColumn { - return when (index) { - 0 -> COLUMN1_KEYS[getInt(DISPLAY_COLUMN_1_KEY, 0)] - 1 -> COLUMN2_KEYS[getInt(DISPLAY_COLUMN_2_KEY, 0)] - else -> { - Timber.w("Unexpected column access: %d", index) - QUESTION - } - } - } - - fun save(prefs: SharedPreferences, columnIndex: Int, value: CardBrowserColumn) { - if (columnIndex != 0 && columnIndex != 1) return - val (key, array) = when (columnIndex) { - 0 -> Pair(DISPLAY_COLUMN_1_KEY, COLUMN1_KEYS) - 1 -> Pair(DISPLAY_COLUMN_2_KEY, COLUMN2_KEYS) - else -> throw IllegalStateException() - } - - Timber.i("updating '%s' to '%s'", key, value) - val index = array.indexOf(value) - if (index == -1) { - Timber.w("illegal value: %s", value) - return - } - prefs.edit { putInt(key, index) } - } + fun fromColumnKey(key: String): CardBrowserColumn = + entries.firstOrNull { it.ankiColumnKey == key } + ?: throw IllegalArgumentException("Invalid key: $key") } } fun List.find(column: CardBrowserColumn): BrowserColumns.Column = - this.first { it.key == column.ankiColumnKey } + this.firstOrNull { it.key == column.ankiColumnKey } + ?: throw IllegalArgumentException("Invalid column: ${column.ankiColumnKey}") diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index e568a5b11302..5bf94bc36196 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -32,7 +32,6 @@ import com.ichi2.anki.CollectionManager.withCol import com.ichi2.anki.DeckSpinnerSelection.Companion.ALL_DECKS_ID import com.ichi2.anki.Flag import com.ichi2.anki.PreviewerDestination -import com.ichi2.anki.browser.CardBrowserColumn.Companion.loadBrowserColumn import com.ichi2.anki.export.ExportDialogFragment.* import com.ichi2.anki.launchCatchingIO import com.ichi2.anki.model.CardStateFilter @@ -135,8 +134,10 @@ class CardBrowserViewModel( private val reverseDirectionFlow = MutableStateFlow(ReverseDirection(orderAsc = false)) val orderAsc get() = reverseDirectionFlow.value.orderAsc - val flowOfColumn1 = MutableStateFlow(sharedPrefs().loadBrowserColumn(0)) - val flowOfColumn2 = MutableStateFlow(sharedPrefs().loadBrowserColumn(1)) + // TODO: Initial values are temporary - set in init { } as they depend on cardsOrNotes + // consider a loading state + val flowOfColumn1 = MutableStateFlow(CardBrowserColumn.QUESTION) + val flowOfColumn2 = MutableStateFlow(CardBrowserColumn.ANSWER) val column1 get() = flowOfColumn1.value val column2 get() = flowOfColumn2.value @@ -276,12 +277,12 @@ class CardBrowserViewModel( flowOfColumn1 .ignoreValuesFromViewModelLaunch() - .onEach { column -> CardBrowserColumn.save(sharedPrefs(), columnIndex = 0, value = column) } + .onEach { column1 -> updateColumnCollection { toUpdate -> toUpdate[0] = column1 } } .launchIn(viewModelScope) flowOfColumn2 .ignoreValuesFromViewModelLaunch() - .onEach { column -> CardBrowserColumn.save(sharedPrefs(), columnIndex = 1, value = column) } + .onEach { column2 -> updateColumnCollection { toUpdate -> toUpdate[1] = column2 } } .launchIn(viewModelScope) performSearchFlow.onEach { @@ -305,6 +306,10 @@ class CardBrowserViewModel( val cardsOrNotes = withCol { CardsOrNotes.fromCollection() } flowOfCardsOrNotes.update { cardsOrNotes } + val columns = BrowserColumnCollection.load(sharedPrefs(), cardsOrNotes) + flowOfColumn1.update { columns.columns[0] } + flowOfColumn2.update { columns.columns[1] } + withCol { sortTypeFlow.update { SortType.fromCol(config, cardsOrNotes, sharedPrefs()) } reverseDirectionFlow.update { ReverseDirection.fromConfig(config) } @@ -766,6 +771,13 @@ class CardBrowserViewModel( flowOfCardsUpdated.emit(Unit) } + private fun updateColumnCollection(block: (MutableList) -> Unit) { + BrowserColumnCollection.update(sharedPrefs(), cardsOrNotes) { + block(it) + return@update true + } + } + suspend fun queryCardIdAtPosition(index: Int): CardId { // TODO: Slow - this will be refactored return queryAllCardIds()[index] @@ -777,8 +789,6 @@ class CardBrowserViewModel( } companion object { - const val DISPLAY_COLUMN_1_KEY = "cardBrowserColumn1" - const val DISPLAY_COLUMN_2_KEY = "cardBrowserColumn2" fun factory( lastDeckIdRepository: LastDeckIdRepository, cacheDir: File, diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/PreferenceUpgradeService.kt b/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/PreferenceUpgradeService.kt index 86ec3864015c..37a60705d3e4 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/PreferenceUpgradeService.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/PreferenceUpgradeService.kt @@ -23,8 +23,11 @@ import androidx.appcompat.app.AppCompatDelegate import androidx.core.content.edit import androidx.core.os.LocaleListCompat import com.ichi2.anki.analytics.UsageAnalytics +import com.ichi2.anki.browser.BrowserColumnCollection +import com.ichi2.anki.browser.CardBrowserColumn import com.ichi2.anki.cardviewer.Gesture import com.ichi2.anki.cardviewer.ViewerCommand +import com.ichi2.anki.model.CardsOrNotes import com.ichi2.anki.noteeditor.CustomToolbarButton import com.ichi2.anki.preferences.sharedPrefs import com.ichi2.anki.reviewer.Binding @@ -99,6 +102,7 @@ object PreferenceUpgradeService { yield(SetShowDeckTitle()) yield(ResetAnalyticsOptIn()) yield(RemoveNoCodeFormatting()) + yield(UpgradeBrowserColumns()) } /** Returns a list of preference upgrade classes which have not been applied */ @@ -500,6 +504,71 @@ object PreferenceUpgradeService { override fun upgrade(preferences: SharedPreferences) = preferences.edit { remove("noCodeFormatting") } } + + internal class UpgradeBrowserColumns : PreferenceUpgrade(19) { + override fun upgrade(preferences: SharedPreferences) { + // Columns were stored as an index into COLUMN[1/2]_KEYS + // This produced a CardBrowserColumn object, and the index was used as an index + // into a string array + + // This has a number of issues: + // * Cards Mode and Notes Mode uses the same column definitions + // * The index was opaque: 0 meant different things in column 1 and column 2 + // * COLUMN[N]_KEYS differed from the available columns in Anki Desktop + // * A user could only select two columns, even on a Tablet/Chromebook/TV + + // To improve this, we define: CardBrowserColumnCollection + // This uses 1 preference for cards or notes mode, rather than 1 preference per + // column + + // The values are now equivalent to the keys which are sent to Anki Desktop + // and allow an arbitrary ordering and number of values + // "activeNoteCols" -> "question|cardEase" + + fun clearLegacyKeys() { + Timber.d("removing legacy keys") + preferences.edit { + remove(DISPLAY_COLUMN_1_KEY) + remove(DISPLAY_COLUMN_2_KEY) + } + } + + val currentColumn1Index = preferences.getInt(DISPLAY_COLUMN_1_KEY, -1) + val currentColumn2Index = preferences.getInt(DISPLAY_COLUMN_2_KEY, -1) + + if (currentColumn1Index == -1 || currentColumn2Index == -1) { + Timber.d("no update needed") + clearLegacyKeys() + return + } + + val currentColumn1 = CardBrowserColumn.COLUMN1_KEYS[currentColumn1Index] + val currentColumn2 = CardBrowserColumn.COLUMN2_KEYS[currentColumn2Index] + + BrowserColumnCollection.update(preferences, CardsOrNotes.CARDS) { columns -> + if (columns.size < 2) return@update false + Timber.d("upgrading browser 'cards' columns") + columns[0] = currentColumn1 + columns[1] = currentColumn2 + true + } + + BrowserColumnCollection.update(preferences, CardsOrNotes.NOTES) { columns -> + if (columns.size < 2) return@update false + Timber.d("upgrading browser 'notes' columns") + columns[0] = currentColumn1 + columns[1] = currentColumn2 + true + } + + clearLegacyKeys() + } + + companion object { + private const val DISPLAY_COLUMN_1_KEY = "cardBrowserColumn1" + private const val DISPLAY_COLUMN_2_KEY = "cardBrowserColumn2" + } + } } } diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt index f91fabd4040f..ca2f8fc2c800 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt @@ -31,9 +31,12 @@ import com.ichi2.anki.CardBrowser.Companion.dueString import com.ichi2.anki.CardBrowser.Companion.nextDue import com.ichi2.anki.IntentHandler.Companion.grantedStoragePermissions import com.ichi2.anki.browser.CardBrowserColumn +import com.ichi2.anki.browser.CardBrowserColumn.CARD +import com.ichi2.anki.browser.CardBrowserColumn.EASE +import com.ichi2.anki.browser.CardBrowserColumn.QUESTION +import com.ichi2.anki.browser.CardBrowserColumn.SFLD +import com.ichi2.anki.browser.CardBrowserColumn.TAGS import com.ichi2.anki.browser.CardBrowserViewModel -import com.ichi2.anki.browser.CardBrowserViewModel.Companion.DISPLAY_COLUMN_1_KEY -import com.ichi2.anki.browser.CardBrowserViewModel.Companion.DISPLAY_COLUMN_2_KEY import com.ichi2.anki.common.utils.isRunningAsUnitTest import com.ichi2.anki.dialogs.DeckSelectionDialog import com.ichi2.anki.model.CardsOrNotes.CARDS @@ -41,6 +44,8 @@ import com.ichi2.anki.model.CardsOrNotes.NOTES import com.ichi2.anki.model.SortType import com.ichi2.anki.scheduling.ForgetCardsViewModel import com.ichi2.anki.servicelayer.NoteService +import com.ichi2.anki.servicelayer.PreferenceUpgradeService +import com.ichi2.libanki.BrowserConfig import com.ichi2.libanki.CardId import com.ichi2.libanki.Consts import com.ichi2.libanki.Note @@ -894,11 +899,13 @@ class CardBrowserTest : RobolectricTest() { } @Test - fun `column spinner positions are set to 0 if no preferences exist`() = runBlocking { + fun `column spinner positions are set if no preferences exist`() = runBlocking { // GIVEN: No shared preferences exist for display column selections getSharedPrefs().edit { - remove(DISPLAY_COLUMN_1_KEY) - remove(DISPLAY_COLUMN_2_KEY) + remove("cardBrowserColumn1") + remove("cardBrowserColumn2") + remove(BrowserConfig.ACTIVE_CARD_COLUMNS_KEY) + remove(BrowserConfig.ACTIVE_NOTE_COLUMNS_KEY) } // WHEN: CardBrowser is created @@ -910,21 +917,52 @@ class CardBrowserTest : RobolectricTest() { val column1SpinnerPosition = column1Spinner.selectedItemPosition val column2SpinnerPosition = column2Spinner.selectedItemPosition - assertThat(column1SpinnerPosition, equalTo(0)) - assertThat(column2SpinnerPosition, equalTo(0)) + val selectedColumn1 = CardBrowserColumn.COLUMN1_KEYS[column1SpinnerPosition] + val selectedColumn2 = CardBrowserColumn.COLUMN2_KEYS[column2SpinnerPosition] + + assertThat(selectedColumn1, equalTo(SFLD)) + assertThat(selectedColumn2, equalTo(CARD)) } @Test fun `column spinner positions are initially set from existing preferences`() = runTest { // GIVEN: Shared preferences exists for display column selections - val index1 = 1 - val index2 = 5 + getSharedPrefs().edit { + putString(BrowserConfig.ACTIVE_CARD_COLUMNS_KEY, "question|cardEase") + } + + // WHEN: CardBrowser is created + val cardBrowser: CardBrowser = getBrowserWithNotes(7) + + // THEN: The display column selections should match the shared preferences values + val column1Spinner = cardBrowser.findViewById(R.id.browser_column1_spinner) + val column2Spinner = cardBrowser.findViewById(R.id.browser_column2_spinner) + val column1SpinnerPosition = column1Spinner.selectedItemPosition + val column2SpinnerPosition = column2Spinner.selectedItemPosition + + val selectedColumn1 = CardBrowserColumn.COLUMN1_KEYS[column1SpinnerPosition] + val selectedColumn2 = CardBrowserColumn.COLUMN2_KEYS[column2SpinnerPosition] + + assertThat(selectedColumn1, equalTo(QUESTION)) + assertThat(selectedColumn2, equalTo(EASE)) + } + + @Test + fun `column spinner positions are upgraded`() = runTest { + // GIVEN: Shared preferences exists for display column selections + // using legacy keys - test of PreferenceUpgradeService getSharedPrefs().edit { - putInt(DISPLAY_COLUMN_1_KEY, index1) - putInt(DISPLAY_COLUMN_2_KEY, index2) + putInt("cardBrowserColumn1", 1) + putInt("cardBrowserColumn2", 5) } + // meta test + assertThat(CardBrowserColumn.COLUMN1_KEYS[1], equalTo(SFLD)) + assertThat(CardBrowserColumn.COLUMN2_KEYS[5], equalTo(TAGS)) + + PreferenceUpgradeService.upgradePreferences(getSharedPrefs(), 20300130) + // WHEN: CardBrowser is created val cardBrowser: CardBrowser = getBrowserWithNotes(7) @@ -934,8 +972,40 @@ class CardBrowserTest : RobolectricTest() { val column1SpinnerPosition = column1Spinner.selectedItemPosition val column2SpinnerPosition = column2Spinner.selectedItemPosition - assertThat(column1SpinnerPosition, equalTo(index1)) - assertThat(column2SpinnerPosition, equalTo(index2)) + val selectedColumn1 = CardBrowserColumn.COLUMN1_KEYS[column1SpinnerPosition] + val selectedColumn2 = CardBrowserColumn.COLUMN2_KEYS[column2SpinnerPosition] + + assertThat(selectedColumn1, equalTo(SFLD)) + assertThat(selectedColumn2, equalTo(TAGS)) + + assertThat("column 1 is cleared", !getSharedPrefs().all.containsKey("cardBrowserColumn1")) + assertThat("column 2 is cleared", !getSharedPrefs().all.containsKey("cardBrowserColumn2")) + } + + @Test + fun `loading corrupt columns returns default`() { + // GIVEN: Shared preferences exists for display column selections + // with a corrupt value + getSharedPrefs().edit { + putString(BrowserConfig.ACTIVE_CARD_COLUMNS_KEY, "question|corrupt") + } + + // WHEN: CardBrowser is created + val cardBrowser: CardBrowser = getBrowserWithNotes(7) + + // THEN: The display column selections should match the shared preferences values + val column1Spinner = cardBrowser.findViewById(R.id.browser_column1_spinner) + val column2Spinner = cardBrowser.findViewById(R.id.browser_column2_spinner) + val column1SpinnerPosition = column1Spinner.selectedItemPosition + val column2SpinnerPosition = column2Spinner.selectedItemPosition + + val selectedColumn1 = CardBrowserColumn.COLUMN1_KEYS[column1SpinnerPosition] + val selectedColumn2 = CardBrowserColumn.COLUMN2_KEYS[column2SpinnerPosition] + + // In future, we may want to keep the 'question' value and only reset + // the corrupt column. + assertThat("column 1 reset to default", selectedColumn1, equalTo(SFLD)) + assertThat("column 2 reset to default", selectedColumn2, equalTo(CARD)) } @Test diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/BrowserColumnCollectionTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/BrowserColumnCollectionTest.kt new file mode 100644 index 000000000000..6a6861f1eb16 --- /dev/null +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/BrowserColumnCollectionTest.kt @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2024 David Allison + * + * 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 . + */ + +package com.ichi2.anki.browser + +import androidx.annotation.CheckResult +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.ichi2.anki.RobolectricTest +import com.ichi2.anki.browser.CardBrowserColumn.DECK +import com.ichi2.anki.browser.CardBrowserColumn.FSRS_STABILITY +import com.ichi2.anki.browser.CardBrowserColumn.SFLD +import com.ichi2.anki.model.CardsOrNotes +import com.ichi2.anki.model.CardsOrNotes.CARDS +import com.ichi2.anki.model.CardsOrNotes.NOTES +import com.ichi2.testutils.getSharedPrefs +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo +import org.hamcrest.Matchers.hasSize +import org.junit.Test +import org.junit.runner.RunWith + +/** @see BrowserColumnCollection */ +@RunWith(AndroidJUnit4::class) +class BrowserColumnCollectionTest : RobolectricTest() { + + val prefs = this.getSharedPrefs() + + @Test + fun `cards - ensure sensible defaults`() { + val default = load(CARDS) + assertThat(default.toKeyArray(), equalTo(listOf("noteFld", "template", "cardDue", "deck"))) + } + + @Test + fun `notes - ensure sensible default`() { + val default = load(NOTES) + assertThat(default.toKeyArray(), equalTo(listOf("noteFld", "note", "template", "noteTags"))) + } + + @Test + fun `cards - update`() { + updateColumns(CARDS) { columns -> columns.add(DECK) } + val updated = load(CARDS) + assertThat(updated.columns.last(), equalTo(DECK)) + } + + @Test + fun `notes - update`() { + updateColumns(NOTES) { columns -> columns.add(DECK) } + val updated = load(NOTES) + assertThat(updated.columns.last(), equalTo(DECK)) + } + + @Test + fun `update with null column`() { + // in AnkiMobile, if you update a column to 'none', the values are rearranged + updateColumns(CARDS) { columns -> + columns.clear() + columns.add(SFLD) + columns.add(null) + columns.add(FSRS_STABILITY) + assertThat("size of updated columns", columns, hasSize(3)) + } + + val updated = load(CARDS) + assertThat("column size", updated.columns, hasSize(2)) + assertThat("first columns is unchanged", updated[0], equalTo(SFLD)) + assertThat("null column is replaced with third", updated[1], equalTo(FSRS_STABILITY)) + } + + private fun BrowserColumnCollection.toKeyArray() = + columns.map { it.ankiColumnKey } + + @CheckResult + private fun load(cardsOrNotes: CardsOrNotes) = + BrowserColumnCollection.load(prefs, cardsOrNotes) + + private fun updateColumns( + cardsOrNotes: CardsOrNotes, + block: (MutableList) -> Unit + ) { + BrowserColumnCollection.update(prefs, cardsOrNotes) { + block(it) + return@update true + } + } +} diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index 4bb09a1d2765..aca9887ae7e5 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -27,6 +27,7 @@ import com.ichi2.anki.Flag import com.ichi2.anki.NoteEditor import com.ichi2.anki.browser.CardBrowserColumn.ANSWER import com.ichi2.anki.browser.CardBrowserColumn.CARD +import com.ichi2.anki.browser.CardBrowserColumn.NOTE_TYPE import com.ichi2.anki.browser.CardBrowserColumn.QUESTION import com.ichi2.anki.browser.CardBrowserColumn.SFLD import com.ichi2.anki.browser.CardBrowserLaunchOptions.DeepLink @@ -316,37 +317,73 @@ class CardBrowserViewModelTest : JvmTest() { } @Test - fun `changing column index 1`() = runViewModelTest { + fun `cards - changing column index 1`() = runViewModelTest { flowOfColumn1.test { ignoreEventsDuringViewModelInit() - assertThat("default column1 value", column1, equalTo(QUESTION)) + assertThat("default column1 value", column1, equalTo(SFLD)) - setColumn1(SFLD) + setColumn1(QUESTION) - assertThat("flowOfColumn1", awaitItem(), equalTo(SFLD)) - assertThat("column1", column1, equalTo(SFLD)) + assertThat("flowOfColumn1", awaitItem(), equalTo(QUESTION)) + assertThat("column1", column1, equalTo(QUESTION)) // expect no change if the value is selected again - setColumn1(SFLD) + setColumn1(QUESTION) expectNoEvents() } } @Test - fun `changing column index 2`() = runViewModelTest { + fun `cards - changing column index 2`() = runViewModelTest { flowOfColumn2.test { ignoreEventsDuringViewModelInit() - assertThat("default column2Index value", column2, equalTo(ANSWER)) + assertThat("default column2Index value", column2, equalTo(CARD)) - setColumn2(CARD) + setColumn2(ANSWER) - assertThat("flowOfColumnIndex2", awaitItem(), equalTo(CARD)) - assertThat("column2Index", column2, equalTo(CARD)) + assertThat("flowOfColumnIndex2", awaitItem(), equalTo(ANSWER)) + assertThat("column2Index", column2, equalTo(ANSWER)) // expect no change if the value is selected again - setColumn2(CARD) + setColumn2(ANSWER) + expectNoEvents() + } + } + + @Test + fun `notes - changing column index 1`() = runViewModelNotesTest { + flowOfColumn1.test { + ignoreEventsDuringViewModelInit() + + assertThat("default column1 value", column1, equalTo(SFLD)) + + setColumn1(QUESTION) + + assertThat("flowOfColumn1", awaitItem(), equalTo(QUESTION)) + assertThat("column1", column1, equalTo(QUESTION)) + + // expect no change if the value is selected again + setColumn1(QUESTION) + expectNoEvents() + } + } + + @Test + fun `notes - changing column index 2`() = runViewModelNotesTest { + flowOfColumn2.test { + ignoreEventsDuringViewModelInit() + + assertThat("default column2Index value", column2, equalTo(NOTE_TYPE)) + + setColumn2(ANSWER) + + assertThat("flowOfColumnIndex2", awaitItem(), equalTo(ANSWER)) + assertThat("column2Index", column2, equalTo(ANSWER)) + + // expect no change if the value is selected again + setColumn2(ANSWER) expectNoEvents() } } From 4934841fa71cbf263814b26f1e5171f5bad91902 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Sun, 16 Jun 2024 00:45:26 +0100 Subject: [PATCH 098/138] feat: setActiveBrowserColumns For use in browserRowForId Prep for Issue 11889 --- .../java/com/ichi2/anki/browser/BrowserColumnCollection.kt | 1 + .../main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt | 3 +++ 2 files changed, 4 insertions(+) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt index 0639604cbb07..c84f04a9a7da 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt @@ -41,6 +41,7 @@ import timber.log.Timber * @see BrowserConfig.activeColumnsKey */ class BrowserColumnCollection(val columns: List) { + val backendKeys: Iterable get() = columns.map { it.ankiColumnKey } val count = columns.size operator fun get(index: Int) = columns[index] diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index 5bf94bc36196..40db3defc14b 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -310,6 +310,9 @@ class CardBrowserViewModel( flowOfColumn1.update { columns.columns[0] } flowOfColumn2.update { columns.columns[1] } + // This impacts browserRowForId(), which we do not use yet + withCol { backend.setActiveBrowserColumns(columns.backendKeys) } + withCol { sortTypeFlow.update { SortType.fromCol(config, cardsOrNotes, sharedPrefs()) } reverseDirectionFlow.update { ReverseDirection.fromConfig(config) } From 18428588198474bb996b42492a9ae54f2667cef5 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Sun, 16 Jun 2024 07:08:50 +0100 Subject: [PATCH 099/138] feat(browser): use backend column headings removes strings: * browser_column1_headings * browser_column2_headings Prep for Issue 11889 --- .../main/java/com/ichi2/anki/CardBrowser.kt | 98 ++++++++++++------- .../anki/browser/BrowserColumnCollection.kt | 2 +- .../ichi2/anki/browser/CardBrowserColumn.kt | 5 +- .../anki/browser/CardBrowserViewModel.kt | 33 +++++-- AnkiDroid/src/main/res/values/02-strings.xml | 22 ----- .../java/com/ichi2/anki/CardBrowserTest.kt | 71 ++++++++++++++ .../anki/browser/CardBrowserViewModelTest.kt | 17 ++++ 7 files changed, 183 insertions(+), 65 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt index 7a1ec3a210b4..6c49f9db9d32 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt @@ -50,6 +50,7 @@ import com.ichi2.anki.browser.CardBrowserViewModel.* import com.ichi2.anki.browser.PreviewerIdsFile import com.ichi2.anki.browser.SaveSearchResult import com.ichi2.anki.browser.SharedPreferencesLastDeckIdRepository +import com.ichi2.anki.browser.getLabel import com.ichi2.anki.browser.toCardBrowserLaunchOptions import com.ichi2.anki.common.utils.android.isRobolectric import com.ichi2.anki.dialogs.* @@ -407,10 +408,18 @@ open class CardBrowser : } } fun onSelectedRowsChanged(rows: Set) = onSelectionChanged() - fun onColumn1Changed(column: CardBrowserColumn) = + fun onColumn1Changed(column: CardBrowserColumn) { cardsAdapter.updateMapping { it[0] = column } - fun onColumn2Changed(column: CardBrowserColumn) = + findViewById(R.id.browser_column1_spinner) + .setSelection(COLUMN1_KEYS.indexOf(column)) + } + + fun onColumn2Changed(column: CardBrowserColumn) { cardsAdapter.updateMapping { it[1] = column } + findViewById(R.id.browser_column2_spinner) + .setSelection(COLUMN2_KEYS.indexOf(column)) + } + fun onFilterQueryChanged(filterQuery: String) { // setQuery before expand does not set the view's value searchItem!!.expandActionView() @@ -462,10 +471,62 @@ open class CardBrowser : } } } + + fun setupColumnSpinners() { + // Create a spinner for column 1 + findViewById(R.id.browser_column1_spinner).apply { + adapter = ArrayAdapter( + this@CardBrowser, + android.R.layout.simple_spinner_item, + viewModel.column1Candidates.map { it.getLabel(viewModel.cardsOrNotes) } + ).apply { + setDropDownViewResource(R.layout.spinner_custom_layout) + } + onItemSelectedListener = BasicItemSelectedListener { pos, _ -> + viewModel.setColumn1(COLUMN1_KEYS[pos]) + } + setSelection(COLUMN1_KEYS.indexOf(viewModel.column1)) + } + + // Setup the column 2 heading as a spinner so that users can easily change the column type + findViewById(R.id.browser_column2_spinner).apply { + adapter = ArrayAdapter( + this@CardBrowser, + android.R.layout.simple_spinner_item, + viewModel.column2Candidates.map { it.getLabel(viewModel.cardsOrNotes) } + ).apply { + // The custom layout for the adapter is used to prevent the overlapping of various interactive components on the screen + setDropDownViewResource(R.layout.spinner_custom_layout) + } + // Create a new list adapter with updated column map any time the user changes the column + onItemSelectedListener = BasicItemSelectedListener { pos, _ -> + viewModel.setColumn2(COLUMN2_KEYS[pos]) + } + setSelection(COLUMN2_KEYS.indexOf(viewModel.column2)) + } + } + fun initCompletedChanged(completed: Boolean) { - if (completed) searchCards() + if (!completed) return + + setupColumnSpinners() + searchCards() } + @Suppress("UNCHECKED_CAST") // as? ArrayAdapter? + fun cardsOrNotesChanged(cardsOrNotes: CardsOrNotes) { + Timber.d("mode change: %s - updating spinner titles", cardsOrNotes) + findViewById(R.id.browser_column1_spinner)?.adapter?.apply { + val adapter = this as? ArrayAdapter? ?: return@apply + adapter.clear() + adapter.addAll(viewModel.column1Candidates.map { it.getLabel(cardsOrNotes) }) + } + findViewById(R.id.browser_column2_spinner)?.adapter?.apply { + val adapter = this as? ArrayAdapter? ?: return@apply + adapter.clear() + adapter.addAll(viewModel.column2Candidates.map { it.getLabel(cardsOrNotes) }) + } + } viewModel.flowOfIsTruncated.launchCollectionInLifecycleScope(::onIsTruncatedChanged) viewModel.flowOfSearchQueryExpanded.launchCollectionInLifecycleScope(::onSearchQueryExpanded) viewModel.flowOfSelectedRows.launchCollectionInLifecycleScope(::onSelectedRowsChanged) @@ -478,6 +539,7 @@ open class CardBrowser : viewModel.flowOfCardsUpdated.launchCollectionInLifecycleScope(::cardsUpdatedChanged) viewModel.flowOfSearchState.launchCollectionInLifecycleScope(::searchStateChanged) viewModel.flowOfInitCompleted.launchCollectionInLifecycleScope(::initCompletedChanged) + viewModel.flowOfCardsOrNotes.launchCollectionInLifecycleScope(::cardsOrNotesChanged) } // Finish initializing the activity after the collection has been correctly loaded @@ -486,36 +548,6 @@ open class CardBrowser : Timber.d("onCollectionLoaded()") registerExternalStorageListener() cards.reset() - // Create a spinner for column 1 - findViewById(R.id.browser_column1_spinner).apply { - adapter = ArrayAdapter.createFromResource( - this@CardBrowser, - R.array.browser_column1_headings, - android.R.layout.simple_spinner_item - ).apply { - setDropDownViewResource(R.layout.spinner_custom_layout) - } - onItemSelectedListener = BasicItemSelectedListener { pos, _ -> - viewModel.setColumn1(COLUMN1_KEYS[pos]) - } - setSelection(COLUMN1_KEYS.indexOf(viewModel.column1)) - } - // Setup the column 2 heading as a spinner so that users can easily change the column type - findViewById(R.id.browser_column2_spinner).apply { - adapter = ArrayAdapter.createFromResource( - this@CardBrowser, - R.array.browser_column2_headings, - android.R.layout.simple_spinner_item - ).apply { - // The custom layout for the adapter is used to prevent the overlapping of various interactive components on the screen - setDropDownViewResource(R.layout.spinner_custom_layout) - } - // Create a new list adapter with updated column map any time the user changes the column - onItemSelectedListener = BasicItemSelectedListener { pos, _ -> - viewModel.setColumn2(COLUMN2_KEYS[pos]) - } - setSelection(COLUMN2_KEYS.indexOf(viewModel.column2)) - } cardsListView.setOnItemClickListener { _: AdapterView<*>?, view: View?, position: Int, _: Long -> if (viewModel.isInMultiSelectMode) { diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt index c84f04a9a7da..6a64b2af9446 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt @@ -84,7 +84,7 @@ class BrowserColumnCollection(val columns: List) { val key = mode.toPreferenceKey() val preferenceValue = value.columns .joinToString(separator = SEPARATOR_CHAR.toString()) { it.ankiColumnKey } - Timber.d("updating '%s' to '%s'", key, preferenceValue) + Timber.d("updating '%s' [%s] to '%s'", key, mode, preferenceValue) prefs.edit { putString(key, preferenceValue) } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt index f687951b3e0d..383b617370b4 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserColumn.kt @@ -18,14 +18,13 @@ package com.ichi2.anki.browser import anki.search.BrowserColumns import com.ichi2.anki.CardBrowser -import com.ichi2.anki.R import net.ankiweb.rsdroid.Backend /** * A column available in the [browser][CardBrowser] * - * @see COLUMN1_KEYS: maps to [R.array.browser_column1_headings] - * @see COLUMN2_KEYS: maps to [R.array.browser_column2_headings] + * @see COLUMN1_KEYS - values for first column + * @see COLUMN2_KEYS - values for second column * @see CardBrowser.CardCache.getColumnHeaderText - how columns are rendered * * @param ankiColumnKey The key used in [Backend.setActiveBrowserColumns] diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index 40db3defc14b..61d683e0f39a 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -26,6 +26,7 @@ import androidx.lifecycle.viewmodel.initializer import androidx.lifecycle.viewmodel.viewModelFactory import anki.collection.OpChanges import anki.collection.OpChangesWithCount +import anki.search.BrowserColumns import com.ichi2.anki.AnkiDroidApp import com.ichi2.anki.CardBrowser import com.ichi2.anki.CollectionManager.withCol @@ -122,7 +123,7 @@ class CardBrowserViewModel( * Whether the browser is working in Cards mode or Notes mode. * default: [CARDS] * */ - private val flowOfCardsOrNotes = MutableStateFlow(CARDS) + val flowOfCardsOrNotes = MutableStateFlow(CARDS) val cardsOrNotes get() = flowOfCardsOrNotes.value // card that was clicked (not marked) @@ -141,6 +142,12 @@ class CardBrowserViewModel( val column1 get() = flowOfColumn1.value val column2 get() = flowOfColumn2.value + /** Potential headings for the first column */ + lateinit var column1Candidates: List + + /** Potential headings for the second column */ + lateinit var column2Candidates: List + val flowOfSearchQueryExpanded = MutableStateFlow(false) private val searchQueryInputFlow = MutableStateFlow(null) @@ -306,12 +313,11 @@ class CardBrowserViewModel( val cardsOrNotes = withCol { CardsOrNotes.fromCollection() } flowOfCardsOrNotes.update { cardsOrNotes } - val columns = BrowserColumnCollection.load(sharedPrefs(), cardsOrNotes) - flowOfColumn1.update { columns.columns[0] } - flowOfColumn2.update { columns.columns[1] } + val allColumns = withCol { allBrowserColumns() }.associateBy { it.key } + column1Candidates = CardBrowserColumn.COLUMN1_KEYS.map { allColumns[it.ankiColumnKey]!! } + column2Candidates = CardBrowserColumn.COLUMN2_KEYS.map { allColumns[it.ankiColumnKey]!! } - // This impacts browserRowForId(), which we do not use yet - withCol { backend.setActiveBrowserColumns(columns.backendKeys) } + setupColumns(cardsOrNotes) withCol { sortTypeFlow.update { SortType.fromCol(config, cardsOrNotes, sharedPrefs()) } @@ -325,6 +331,16 @@ class CardBrowserViewModel( } } + private suspend fun setupColumns(cardsOrNotes: CardsOrNotes) { + Timber.d("loading columns columns for %s mode", cardsOrNotes) + val columns = BrowserColumnCollection.load(sharedPrefs(), cardsOrNotes) + flowOfColumn1.update { columns.columns[0] } + flowOfColumn2.update { columns.columns[1] } + + // This impacts browserRowForId(), which we do not use yet + withCol { backend.setActiveBrowserColumns(columns.backendKeys) } + } + @VisibleForTesting fun manualInit() { require(manualInit) { "'manualInit' should be true" } @@ -385,6 +401,7 @@ class CardBrowserViewModel( newValue.saveToCollection() } flowOfCardsOrNotes.update { newValue } + setupColumns(newValue) } fun setTruncated(value: Boolean) { @@ -775,6 +792,7 @@ class CardBrowserViewModel( } private fun updateColumnCollection(block: (MutableList) -> Unit) { + Timber.d("updateColumnCollection") BrowserColumnCollection.update(sharedPrefs(), cardsOrNotes) { block(it) return@update true @@ -891,3 +909,6 @@ class PreviewerIdsFile(path: String) : File(path), Parcelable { } } } + +fun BrowserColumns.Column.getLabel(cardsOrNotes: CardsOrNotes): String = + if (cardsOrNotes == CARDS) cardsModeLabel else notesModeLabel diff --git a/AnkiDroid/src/main/res/values/02-strings.xml b/AnkiDroid/src/main/res/values/02-strings.xml index 04d08486ae0e..7873642bb4c6 100644 --- a/AnkiDroid/src/main/res/values/02-strings.xml +++ b/AnkiDroid/src/main/res/values/02-strings.xml @@ -59,28 +59,6 @@ System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - - Flags diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt index ca2f8fc2c800..55caf4e1618d 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt @@ -32,6 +32,7 @@ import com.ichi2.anki.CardBrowser.Companion.nextDue import com.ichi2.anki.IntentHandler.Companion.grantedStoragePermissions import com.ichi2.anki.browser.CardBrowserColumn import com.ichi2.anki.browser.CardBrowserColumn.CARD +import com.ichi2.anki.browser.CardBrowserColumn.DECK import com.ichi2.anki.browser.CardBrowserColumn.EASE import com.ichi2.anki.browser.CardBrowserColumn.QUESTION import com.ichi2.anki.browser.CardBrowserColumn.SFLD @@ -61,6 +62,7 @@ import com.ichi2.testutils.TestClass import com.ichi2.testutils.getSharedPrefs import com.ichi2.ui.FixedTextView import com.ichi2.utils.LanguageUtil +import com.ichi2.utils.UiUtil.setSelectedValue import io.mockk.every import io.mockk.mockkObject import io.mockk.mockkStatic @@ -1008,6 +1010,20 @@ class CardBrowserTest : RobolectricTest() { assertThat("column 2 reset to default", selectedColumn2, equalTo(CARD)) } + @Test + @Ignore("issues with launchCollectionInLifecycleScope") + fun `column titles update when moving to notes mode`() = withBrowser { + val column2Spinner = findViewById(R.id.browser_column2_spinner) + column2Spinner.setSelectedValue("Interval") + + assertThat("spinner title: cards", column2Spinner.selectedItem, equalTo("Interval")) + + viewModel.setCardsOrNotes(NOTES) + waitForAsyncTasksToComplete() + + assertThat("spinner title: notes", column2Spinner.selectedItem, equalTo("Avg. Interval")) + } + @Test fun `tapping row toggles state - Issue 14952`() = runTest { // tapping the row was broken, checkbox was fine @@ -1177,6 +1193,46 @@ class CardBrowserTest : RobolectricTest() { assertThat(question, equalTo("")) } + @Test + fun `initial value is correct column`() { + // Column 1 is [QUESTION, SFLD], the values when [SFLD] is selected + + addNoteUsingBasicAndReversedModel("Hello", "World") + + withBrowser { + assertThat(viewModel.column1, equalTo(SFLD)) + + assertThat(column1Text(row = 0), equalTo("Hello")) + assertThat(column1Text(row = 1), equalTo("Hello")) + } + } + + @Test + @Ignore( + "issues with launchCollectionInLifecycleScope - provided value is not current" + + "use an integration test" + ) + fun `column text is updated - cardsOrNotes and column change`() { + addNoteUsingBasicAndReversedModel("Hello", "World") + + withBrowser { + assertThat("cards: original column", column2TitleText, equalTo("Card Type")) + + setColumn2(DECK) + assertThat("cards: changed column", column2TitleText, equalTo("Deck")) + + viewModel.setCardsOrNotes(NOTES) + waitForAsyncTasksToComplete() + + assertThat("notes: default column", column2TitleText, equalTo("Note Type")) + setColumn2(DECK) + assertThat("notes: changed column", column2TitleText, equalTo("Avg. Due")) + + viewModel.setCardsOrNotes(CARDS) + assertThat("cards: updated column used", column2TitleText, equalTo("Deck")) + } + } + fun NotetypeJson.addNote(field: String, vararg fields: String): Note { return addNoteUsingModelName(this.name, field, *fields) } @@ -1200,6 +1256,21 @@ fun CardBrowser.replaceSelectionWith(positions: IntArray) { selectRowsWithPositions(*positions) } +private val CardBrowser.column2TitleText: String + get() = findViewById(R.id.browser_column2_spinner) + .selectedItem.toString() + +private fun CardBrowser.setColumn2(col: CardBrowserColumn) { + findViewById(R.id.browser_column2_spinner) + .setSelection(CardBrowserColumn.COLUMN2_KEYS.indexOf(col)) +} + +fun CardBrowser.column1Text(row: Int): CharSequence? { + val rowView = cardsAdapter.getView(row, null, cardsListView) + val column1 = rowView.findViewById(R.id.card_sfld) + return column1.text +} + fun CardBrowser.selectRowsWithPositions(vararg positions: Int) { // PREF: inefficient as the card flow is updated each iteration positions.forEach { pos -> diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index aca9887ae7e5..6984f0c0dc8f 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -27,6 +27,7 @@ import com.ichi2.anki.Flag import com.ichi2.anki.NoteEditor import com.ichi2.anki.browser.CardBrowserColumn.ANSWER import com.ichi2.anki.browser.CardBrowserColumn.CARD +import com.ichi2.anki.browser.CardBrowserColumn.FSRS_DIFFICULTY import com.ichi2.anki.browser.CardBrowserColumn.NOTE_TYPE import com.ichi2.anki.browser.CardBrowserColumn.QUESTION import com.ichi2.anki.browser.CardBrowserColumn.SFLD @@ -560,6 +561,22 @@ class CardBrowserViewModelTest : JvmTest() { assertThat(ids.single(), equalTo(cards[0].card.nid)) } + @Test + fun `changing note types changes columns`() = runViewModelTest { + // BrowserColumnCollection contains BOTH notes and cards column configs + BrowserColumnCollection.update(sharedPrefs(), CardsOrNotes.NOTES) { + it[0] = QUESTION + it[1] = FSRS_DIFFICULTY + true + } + + assertThat("column 2 before", column2, not(equalTo(FSRS_DIFFICULTY))) + + setCardsOrNotes(CardsOrNotes.NOTES) + + assertThat("column 2 after", column2, equalTo(FSRS_DIFFICULTY)) + } + @Test fun `cards - delete one`() = runViewModelTest(notes = 2) { assertThat("initial card count", col.cardCount(), equalTo(2)) From 5c8919fc71b24bbff1ee5a58fc3ed8e069e1d0c3 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Sun, 16 Jun 2024 07:39:16 +0100 Subject: [PATCH 100/138] fix(browser): remove redundant ViewModel call unnecessary logging from logs of 'setColumn[1/2]' --- AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt index 6c49f9db9d32..e0937cd68c32 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt @@ -482,10 +482,10 @@ open class CardBrowser : ).apply { setDropDownViewResource(R.layout.spinner_custom_layout) } + setSelection(COLUMN1_KEYS.indexOf(viewModel.column1)) onItemSelectedListener = BasicItemSelectedListener { pos, _ -> viewModel.setColumn1(COLUMN1_KEYS[pos]) } - setSelection(COLUMN1_KEYS.indexOf(viewModel.column1)) } // Setup the column 2 heading as a spinner so that users can easily change the column type @@ -498,11 +498,11 @@ open class CardBrowser : // The custom layout for the adapter is used to prevent the overlapping of various interactive components on the screen setDropDownViewResource(R.layout.spinner_custom_layout) } + setSelection(COLUMN2_KEYS.indexOf(viewModel.column2)) // Create a new list adapter with updated column map any time the user changes the column onItemSelectedListener = BasicItemSelectedListener { pos, _ -> viewModel.setColumn2(COLUMN2_KEYS[pos]) } - setSelection(COLUMN2_KEYS.indexOf(viewModel.column2)) } } From 7a48bf2e383fe70abb43c5f9a8c8cd52102345db Mon Sep 17 00:00:00 2001 From: AnkiDroid Translations Date: Wed, 19 Jun 2024 13:17:14 +0000 Subject: [PATCH 101/138] Updated strings from Crowdin --- .../src/main/res/values-af/02-strings.xml | 21 ------------------- .../src/main/res/values-am/02-strings.xml | 21 ------------------- .../src/main/res/values-ar/02-strings.xml | 21 ------------------- .../src/main/res/values-az/02-strings.xml | 21 ------------------- .../src/main/res/values-be/02-strings.xml | 21 ------------------- .../src/main/res/values-bg/02-strings.xml | 21 ------------------- .../src/main/res/values-bn/02-strings.xml | 21 ------------------- .../src/main/res/values-ca/02-strings.xml | 21 ------------------- .../src/main/res/values-ckb/02-strings.xml | 21 ------------------- .../src/main/res/values-cs/02-strings.xml | 21 ------------------- .../src/main/res/values-da/02-strings.xml | 21 ------------------- AnkiDroid/src/main/res/values-de/01-core.xml | 6 +++--- .../src/main/res/values-de/02-strings.xml | 21 ------------------- .../src/main/res/values-de/03-dialogs.xml | 2 +- .../src/main/res/values-el/02-strings.xml | 21 ------------------- .../src/main/res/values-eo/02-strings.xml | 21 ------------------- .../src/main/res/values-es-rAR/02-strings.xml | 21 ------------------- .../src/main/res/values-es-rES/02-strings.xml | 21 ------------------- .../src/main/res/values-et/02-strings.xml | 21 ------------------- .../src/main/res/values-eu/02-strings.xml | 21 ------------------- .../src/main/res/values-fa/02-strings.xml | 21 ------------------- .../src/main/res/values-fi/02-strings.xml | 21 ------------------- .../src/main/res/values-fil/02-strings.xml | 21 ------------------- .../src/main/res/values-fr/02-strings.xml | 21 ------------------- .../src/main/res/values-fy/02-strings.xml | 21 ------------------- .../src/main/res/values-ga/02-strings.xml | 21 ------------------- .../src/main/res/values-gl/02-strings.xml | 21 ------------------- .../src/main/res/values-got/02-strings.xml | 21 ------------------- .../src/main/res/values-gu/02-strings.xml | 21 ------------------- .../src/main/res/values-heb/02-strings.xml | 21 ------------------- .../src/main/res/values-hi/02-strings.xml | 21 ------------------- .../src/main/res/values-hr/02-strings.xml | 21 ------------------- .../src/main/res/values-hu/02-strings.xml | 21 ------------------- .../src/main/res/values-hy/02-strings.xml | 21 ------------------- .../src/main/res/values-ind/02-strings.xml | 21 ------------------- .../src/main/res/values-is/02-strings.xml | 21 ------------------- .../src/main/res/values-it/02-strings.xml | 21 ------------------- .../src/main/res/values-iw/02-strings.xml | 21 ------------------- AnkiDroid/src/main/res/values-ja/01-core.xml | 6 +++--- .../src/main/res/values-ja/02-strings.xml | 21 ------------------- .../src/main/res/values-ja/03-dialogs.xml | 2 +- .../src/main/res/values-jv/02-strings.xml | 21 ------------------- .../src/main/res/values-ka/02-strings.xml | 21 ------------------- .../src/main/res/values-kk/02-strings.xml | 21 ------------------- .../src/main/res/values-km/02-strings.xml | 21 ------------------- .../src/main/res/values-kn/02-strings.xml | 21 ------------------- .../src/main/res/values-ko/02-strings.xml | 21 ------------------- .../src/main/res/values-ku/02-strings.xml | 21 ------------------- .../src/main/res/values-ky/02-strings.xml | 21 ------------------- .../src/main/res/values-lt/02-strings.xml | 21 ------------------- .../src/main/res/values-lv/02-strings.xml | 21 ------------------- .../src/main/res/values-mk/02-strings.xml | 21 ------------------- .../src/main/res/values-ml/02-strings.xml | 21 ------------------- .../src/main/res/values-mn/02-strings.xml | 21 ------------------- .../src/main/res/values-mr/02-strings.xml | 21 ------------------- .../src/main/res/values-ms/02-strings.xml | 21 ------------------- .../src/main/res/values-my/02-strings.xml | 21 ------------------- .../src/main/res/values-nl/02-strings.xml | 21 ------------------- .../src/main/res/values-nn/02-strings.xml | 21 ------------------- .../src/main/res/values-no/02-strings.xml | 21 ------------------- .../src/main/res/values-or/02-strings.xml | 21 ------------------- .../src/main/res/values-pa/02-strings.xml | 21 ------------------- .../src/main/res/values-pl/02-strings.xml | 21 ------------------- .../src/main/res/values-pt-rBR/02-strings.xml | 21 ------------------- .../src/main/res/values-pt-rPT/02-strings.xml | 21 ------------------- .../src/main/res/values-ro/02-strings.xml | 21 ------------------- .../src/main/res/values-ru/02-strings.xml | 21 ------------------- .../src/main/res/values-sat/02-strings.xml | 21 ------------------- .../src/main/res/values-sc/02-strings.xml | 21 ------------------- .../src/main/res/values-sk/02-strings.xml | 21 ------------------- .../src/main/res/values-sl/02-strings.xml | 21 ------------------- .../src/main/res/values-sq/02-strings.xml | 21 ------------------- .../src/main/res/values-sr/02-strings.xml | 21 ------------------- .../src/main/res/values-ss/02-strings.xml | 21 ------------------- .../src/main/res/values-sv/02-strings.xml | 21 ------------------- .../src/main/res/values-sw/02-strings.xml | 21 ------------------- .../src/main/res/values-ta/02-strings.xml | 21 ------------------- .../src/main/res/values-te/02-strings.xml | 21 ------------------- .../src/main/res/values-tg/02-strings.xml | 21 ------------------- .../src/main/res/values-tgl/02-strings.xml | 21 ------------------- .../src/main/res/values-th/02-strings.xml | 21 ------------------- .../src/main/res/values-ti/02-strings.xml | 21 ------------------- .../src/main/res/values-tn/02-strings.xml | 21 ------------------- .../src/main/res/values-tr/02-strings.xml | 21 ------------------- .../src/main/res/values-ts/02-strings.xml | 21 ------------------- .../src/main/res/values-tt/02-strings.xml | 21 ------------------- .../src/main/res/values-uk/02-strings.xml | 21 ------------------- .../src/main/res/values-ur/02-strings.xml | 21 ------------------- .../src/main/res/values-uz/02-strings.xml | 21 ------------------- .../src/main/res/values-ve/02-strings.xml | 21 ------------------- .../src/main/res/values-vi/02-strings.xml | 21 ------------------- .../src/main/res/values-wo/02-strings.xml | 21 ------------------- .../src/main/res/values-xh/02-strings.xml | 21 ------------------- .../src/main/res/values-yue/02-strings.xml | 21 ------------------- .../src/main/res/values-zh-rCN/01-core.xml | 4 ++-- .../src/main/res/values-zh-rCN/02-strings.xml | 21 ------------------- .../src/main/res/values-zh-rTW/02-strings.xml | 21 ------------------- .../src/main/res/values-zu/02-strings.xml | 21 ------------------- 98 files changed, 10 insertions(+), 1963 deletions(-) diff --git a/AnkiDroid/src/main/res/values-af/02-strings.xml b/AnkiDroid/src/main/res/values-af/02-strings.xml index 3da6c40d7ab6..18b3757b2cf7 100644 --- a/AnkiDroid/src/main/res/values-af/02-strings.xml +++ b/AnkiDroid/src/main/res/values-af/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Vraag - Sort field - - - Antwoord - Kaart - Pak - Nota - Vraag - Etikette - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-am/02-strings.xml b/AnkiDroid/src/main/res/values-am/02-strings.xml index f36cc4a2c47e..f7d2d304f631 100644 --- a/AnkiDroid/src/main/res/values-am/02-strings.xml +++ b/AnkiDroid/src/main/res/values-am/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-ar/02-strings.xml b/AnkiDroid/src/main/res/values-ar/02-strings.xml index c9b9cc5883fd..bf5a6687cfbf 100644 --- a/AnkiDroid/src/main/res/values-ar/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ar/02-strings.xml @@ -80,27 +80,6 @@ خطأ قاتل: توقف معالج عارض الويب عن العمل. السبب: %s فشل في معالجة عارض الويب الخاص بالنظام فشل عارض ويب النظام في عرض البطاقة %1$s.\n %2$s - - - سؤال - حقل الفرز - - - جواب - بطاقة - رزمة - ملحوظة - سؤال - وسوم - هفوات - مراجعات - التباعد - سهولة - تاريخ الاستحقاق - تاريخ تعديل البطاقة - تاريخ الإنشاء - تاريخ تعديل الملحوظة - أعلام تعديل الحد اليومي للبطاقات الجديدة diff --git a/AnkiDroid/src/main/res/values-az/02-strings.xml b/AnkiDroid/src/main/res/values-az/02-strings.xml index 5757f3cf2293..e5526b172be6 100644 --- a/AnkiDroid/src/main/res/values-az/02-strings.xml +++ b/AnkiDroid/src/main/res/values-az/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-be/02-strings.xml b/AnkiDroid/src/main/res/values-be/02-strings.xml index b33d3e5e7077..0dcfc9f5a2fb 100644 --- a/AnkiDroid/src/main/res/values-be/02-strings.xml +++ b/AnkiDroid/src/main/res/values-be/02-strings.xml @@ -80,27 +80,6 @@ Крытычная памылка: збой апрацоўшчыка WebView. Прычына: %s Памылка апрацоўшчыка сістэмнага WebView Сістэмнаму WebView не атрымалася апрацаваць картку \'%1$s\'.\n %2$s - - - Пытанне - Поле сартавання - - - Адказ - Картка - Калода - Нататка - Пытанне - Меткі - Памылковых - Паўтарэнняў - Інтэрвал - Лёгкасць - Засталося - Картка змененая - Створана - Нататка зменена - Сцягі Змяніць абмежаванні новых картак на сёння diff --git a/AnkiDroid/src/main/res/values-bg/02-strings.xml b/AnkiDroid/src/main/res/values-bg/02-strings.xml index f9c1c23de778..de79b074d841 100644 --- a/AnkiDroid/src/main/res/values-bg/02-strings.xml +++ b/AnkiDroid/src/main/res/values-bg/02-strings.xml @@ -80,27 +80,6 @@ Фатална грешка: WebView визуализаторът се срина. Причина: %s Неуспех при системно WebView визуализиране На системното WebView не се получи да покаже картата \'%1$s\'.\n%2$s - - - Въпрос - Поле за сортиране - - - Oтговор - Карта - Тесте - Бележка - Въпрос - Етикети - Пропуски - Разглеждания - Интервал - Лесно - Поради - променена карта - Създадено - променена бележка - Флагове Модифициране на днешното ограничение за нови карти diff --git a/AnkiDroid/src/main/res/values-bn/02-strings.xml b/AnkiDroid/src/main/res/values-bn/02-strings.xml index 806fc6846040..d81d95373966 100644 --- a/AnkiDroid/src/main/res/values-bn/02-strings.xml +++ b/AnkiDroid/src/main/res/values-bn/02-strings.xml @@ -80,27 +80,6 @@ মারাত্মক ত্রুটি: ওয়েবভিউ রেনডারার ক্র্যাশ করেছে। কারণ: %s সিস্টেম ওয়েবভিউ রেন্ডারিং ব্যর্থ সিস্টেম ওয়েব-ভিউ \'%1$s\'.\n %2$s কার্ড রেন্ডার করতে ব্যর্থ হয়েছে - - - প্রশ্ন - ফিল্ড সাজান - - - উত্তর - কার্ড - ডেক - নোট - প্রশ্ন - টেগসমূহ - ভুলে যাওয়া - পরিদর্শন - বিরামকাল - সহজতা - ডিউ - কার্ড পরিবর্তন - রচিত - নোট পরিবর্তিত - নিশান আজকের নতুন কার্ড সীমা বদল diff --git a/AnkiDroid/src/main/res/values-ca/02-strings.xml b/AnkiDroid/src/main/res/values-ca/02-strings.xml index 80ddd513824f..a64648e91d57 100644 --- a/AnkiDroid/src/main/res/values-ca/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ca/02-strings.xml @@ -80,27 +80,6 @@ Error Fatal: El renderitzador de WebView s\'ha penjat. Causa: %s Error al sistema de renderització de WebView El sistema WebView ha fallat al renderitzar la carta \'%1$s.\n%2$s - - - Pregunta - Camp d\'ordenació - - - Resposta - Carta - Paquet - Anotació - Pregunta - Etiquetes - Errades - Revisions - Intèrval - Facilitat - Pendent - Carta modificada - Creada - Nota modificada - Bandera Canviar el límit de cartes noves d\'avui diff --git a/AnkiDroid/src/main/res/values-ckb/02-strings.xml b/AnkiDroid/src/main/res/values-ckb/02-strings.xml index 1b462b99e6cc..4bd10fc19a6c 100644 --- a/AnkiDroid/src/main/res/values-ckb/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ckb/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - پرسیار - Sort field - - - وەڵام - کارت - دەستە - تێبینی - پرسیار - Etîket - Lapses - پێداچوونەوەکان - Interval - Ease - Due - Card Modified - دروستکرا - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-cs/02-strings.xml b/AnkiDroid/src/main/res/values-cs/02-strings.xml index 8eb0d7fa2e07..db9cf309ad8b 100644 --- a/AnkiDroid/src/main/res/values-cs/02-strings.xml +++ b/AnkiDroid/src/main/res/values-cs/02-strings.xml @@ -80,27 +80,6 @@ Kritická chyba: Vykreslování WebView selhalo. Příčina: %s Selhání vykreslování systémového webView Systémovému WebView se nepodařilo vykreslit kartu „%1$s“.\n %2$s - - - Otázka - Pole řazení - - - Odpověď - Karta - Balíček - Poznámka - Otázka - Štítky - Zapomínání - Opakování - Interval - Snadnost - Ke zkoušení - Karta upravena - Vytvořeno - Poznámka upravena - Příznaky Upravit dnešní limit nových karet diff --git a/AnkiDroid/src/main/res/values-da/02-strings.xml b/AnkiDroid/src/main/res/values-da/02-strings.xml index cffbefda6527..4cc4550ab3ad 100644 --- a/AnkiDroid/src/main/res/values-da/02-strings.xml +++ b/AnkiDroid/src/main/res/values-da/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Svar - Kort - Stak - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-de/01-core.xml b/AnkiDroid/src/main/res/values-de/01-core.xml index d1ac9cc323a0..f1a094ebd096 100644 --- a/AnkiDroid/src/main/res/values-de/01-core.xml +++ b/AnkiDroid/src/main/res/values-de/01-core.xml @@ -104,15 +104,15 @@ Ausschließen Notiz löschen Flagge - Rename flags + Flaggen umbenennen Karte markieren Schlagwörter bearbeiten Diese Notiz und alle ihre Karten tatsächlich löschen?\n%s In %1$s nachschlagen Notiz markieren Markierung entfernen - Enable voice playback - Disable voice playback + Sprachausgabe aktivieren + Sprachausgabe deaktivieren Stapel erstellen Gefilterten Stapel erstellen Auf das AnkiDroid-Verzeichnis kann nicht zugegriffen werden diff --git a/AnkiDroid/src/main/res/values-de/02-strings.xml b/AnkiDroid/src/main/res/values-de/02-strings.xml index c4db2cd6e392..5f01c3167802 100644 --- a/AnkiDroid/src/main/res/values-de/02-strings.xml +++ b/AnkiDroid/src/main/res/values-de/02-strings.xml @@ -80,27 +80,6 @@ Schwerer Fehler: WebView-Renderer ist abgestürzt. Grund: %s Fehler beim System-WebView-Rendering System-WebView konnte die Karte »%1$s« nicht rendern.\n %2$s - - - Frage - Sortierfeld - - - Antwort - Karte - Stapel - Notiz - Frage - Schlagwörter - Vergessene - Wiederholungen - Intervall - Leichtigkeit - Fällig - Karte geändert - Erstellt - Notiz geändert - Flaggen Heutiges Limit für neue Karten ändern diff --git a/AnkiDroid/src/main/res/values-de/03-dialogs.xml b/AnkiDroid/src/main/res/values-de/03-dialogs.xml index b56a2c081e07..1d1f830df9cb 100644 --- a/AnkiDroid/src/main/res/values-de/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-de/03-dialogs.xml @@ -257,5 +257,5 @@ Das System-WebView ist veraltet. Einige Funktionen werden nicht korrekt funktionieren. Bitte aktualisieren Sie es.\n\nInstallierte Version: %1$d\nMindestanforderung: %2$d - Confirm all changes before saving + Alle Änderungen vor dem Speichern bestätigen diff --git a/AnkiDroid/src/main/res/values-el/02-strings.xml b/AnkiDroid/src/main/res/values-el/02-strings.xml index 80f56dd84ab8..7bb9f1d1766b 100644 --- a/AnkiDroid/src/main/res/values-el/02-strings.xml +++ b/AnkiDroid/src/main/res/values-el/02-strings.xml @@ -80,27 +80,6 @@ Μοιραίο σφάλμα: Η συσκευή αναπαραγωγής WebView κατέρρευσε. Αιτία: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Ερώτηση - Sort field - - - Απάντηση - Κάρτα - Τράπουλα - Σημείωση - Ερώτηση - Ετικέτες - Lapses - Επαναλήψεις - Διάστημα - Ευκολία - Due - Τροποποιημένες κάρτες - Δημιουργήθηκε - Τροποποιημένες σημειώσεις - Σημαίες Τροποποίηση σημερινού ορίου νέων καρτών diff --git a/AnkiDroid/src/main/res/values-eo/02-strings.xml b/AnkiDroid/src/main/res/values-eo/02-strings.xml index 2a73204c4880..ad902406ced7 100644 --- a/AnkiDroid/src/main/res/values-eo/02-strings.xml +++ b/AnkiDroid/src/main/res/values-eo/02-strings.xml @@ -80,27 +80,6 @@ Neriparebla eraro pri WebView. Kaŭzo: %s Eraro bildigi per sistema WebView La sistema komponanto WebView fiaskis bildigi la karton “%1$s”.\n%2$s - - - Demando - Ordigi laŭ kampo - - - Respondo - Karto - Kartaro - Noto - Demando - Etikedoj - Misrespondoj - Ripetoj - Intertempo - Facileco - Lernenda - Modifis karton - Kreita - Modifis noton - Flagoj Modifi hodiaŭan limigon de novaj kartoj diff --git a/AnkiDroid/src/main/res/values-es-rAR/02-strings.xml b/AnkiDroid/src/main/res/values-es-rAR/02-strings.xml index a0d4f482cca9..fd688199a01a 100644 --- a/AnkiDroid/src/main/res/values-es-rAR/02-strings.xml +++ b/AnkiDroid/src/main/res/values-es-rAR/02-strings.xml @@ -80,27 +80,6 @@ Error fatal: El renderizador de WebView se cayó. Causa: %s Fallo de procesamiento de WebView del sistema WebView del sistema no pudo procesar la tarjeta \'%1$s\'.\n %2$s - - - Pregunta - Campo de ordenamiento - - - Respuesta - Tarjeta - Mazo - Nota - Pregunta - Etiquetas - Intervalos - Repasos - Intervalo - Facilidad - Programadas - Tarjeta modificada - Creado - Nota modificada - Banderas Cambiar el límite de tarjetas nuevas para hoy diff --git a/AnkiDroid/src/main/res/values-es-rES/02-strings.xml b/AnkiDroid/src/main/res/values-es-rES/02-strings.xml index 42bf9a8dd353..7fb2a50fff5d 100644 --- a/AnkiDroid/src/main/res/values-es-rES/02-strings.xml +++ b/AnkiDroid/src/main/res/values-es-rES/02-strings.xml @@ -80,27 +80,6 @@ Error fatal: El renderizador de WebView se cayó. Causa: %s Fallo de procesamiento de WebView del sistema WebView del sistema no pudo procesar la tarjeta \'%1$s\'.\n %2$s - - - Pregunta - Campo de clasificación - - - Respuesta - Tarjeta - Mazo - Nota - Pregunta - Etiquetas - Fallos - Repasos - Intervalo - Facilidad - Programadas - Tarjeta modificada - Creado - Nota modificada - Banderas Cambiar el límite de tarjetas nuevas para hoy diff --git a/AnkiDroid/src/main/res/values-et/02-strings.xml b/AnkiDroid/src/main/res/values-et/02-strings.xml index 577618feb72f..0f38c4d8d7c5 100644 --- a/AnkiDroid/src/main/res/values-et/02-strings.xml +++ b/AnkiDroid/src/main/res/values-et/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Küsimus - Sort field - - - Vastus - Kaart - Kaardipakk - Märkus - Küsimus - Märksõnad - Lapses - Arvustused - Intervall - Ease - Tähtaeg - Kaart muudetud - Loodud - Märge muudetud - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-eu/02-strings.xml b/AnkiDroid/src/main/res/values-eu/02-strings.xml index ed1ba663ee22..4bc9eb4532a0 100644 --- a/AnkiDroid/src/main/res/values-eu/02-strings.xml +++ b/AnkiDroid/src/main/res/values-eu/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Galdera - Ordenatzeko eremua - - - Erantzuna - Txartela - Sorta - Oharra - Galdera - Etiketak - Hutsak - Berrikusketak - Tartea - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-fa/02-strings.xml b/AnkiDroid/src/main/res/values-fa/02-strings.xml index ca2a4f76a754..44708f22304f 100644 --- a/AnkiDroid/src/main/res/values-fa/02-strings.xml +++ b/AnkiDroid/src/main/res/values-fa/02-strings.xml @@ -80,27 +80,6 @@ خطای وخیم: تنظیم‌کنندۀ ظاهر برنامه دچار مشکل شد. دلیل: %s مشکل در سیستم تنظیم‌کنندۀ ظاهر برنامه سیستم در تنظیم ظاهر کارت %1$s با خطا مواجه شد.\n%2$s - - - سوال - مرتب کردن فیلد - - - پاسخ - کارت - مجموعه - یادداشت - پرسش - برچسب ها - دفعات اشتباه - بازبینی ها - بازه - سهولت - موعد مرور - زمان ویرایش کارت - ساخته شده - زمان ویرایش یادداشت - پرچم ها تعیین محدودیت برای کارت جدید امروز diff --git a/AnkiDroid/src/main/res/values-fi/02-strings.xml b/AnkiDroid/src/main/res/values-fi/02-strings.xml index 1c2ab7f2c835..84e8ca329c69 100644 --- a/AnkiDroid/src/main/res/values-fi/02-strings.xml +++ b/AnkiDroid/src/main/res/values-fi/02-strings.xml @@ -80,27 +80,6 @@ Kriittinen virhe: WebView-renderöijä kaatui. Syy: %s Järjestelmän WebView Renderöinti Epäonnistui Järjestelmän WebView ei pystynyt näyttämään korttia \'%1$s\'.\n %2$s - - - Kysymys - Lajittelukenttä - - - Vastaus - Kortti - Pakka - Muistiinpano - Kysymys - Tunnisteet - Virheet - Kertaukset - Kertausväli - Helppous - Erääntynyt - Korttia Muokattu - Luotu - Muistilappua muokattu - Liput Muuta tämän päivän uusien korttien määrän ylärajaa diff --git a/AnkiDroid/src/main/res/values-fil/02-strings.xml b/AnkiDroid/src/main/res/values-fil/02-strings.xml index 6588c9aa89e7..faf87486c870 100644 --- a/AnkiDroid/src/main/res/values-fil/02-strings.xml +++ b/AnkiDroid/src/main/res/values-fil/02-strings.xml @@ -80,27 +80,6 @@ Malubhang Kamalian: Nawask ang renderer ng WebView. Dahilan: %s Bigo ang Pag-Render ng Pansistemang WebView Bigo ang Pansistemang Webview sa pag-render sa card na \'%1$s\'.\n %2$s - - - Tanong - I-sort ang field - - - Sagot - Card - Deck - Tala - Tanong - Mga Tag - Mga Pagkukulang - Mga Repaso - Agwat - Gaan - Takda - Binago ang Card - Nilikha - Binago ang Tala - Mga Watawat Baguhin ang limitasyon sa bagong card ngayong araw diff --git a/AnkiDroid/src/main/res/values-fr/02-strings.xml b/AnkiDroid/src/main/res/values-fr/02-strings.xml index c8fb30d51d7d..3cb42250ed8c 100644 --- a/AnkiDroid/src/main/res/values-fr/02-strings.xml +++ b/AnkiDroid/src/main/res/values-fr/02-strings.xml @@ -80,27 +80,6 @@ Erreur Fatale : Plantage du moteur de rendu Webview. Cause : %s Échec de rendu du système WebView Le système WebView n\'a pas réussi à afficher la carte « %1$s ».\n %2$s - - - Question - Trier - - - Réponse - Carte - Paquet - Note - Question - Étiquettes - Erreurs - Révisions - Intervalle - Facilité - À faire - Carte modifiée - Créée - Note modifiée - Marqueurs Modifier la limite de nouvelles cartes d\'aujourd\'hui diff --git a/AnkiDroid/src/main/res/values-fy/02-strings.xml b/AnkiDroid/src/main/res/values-fy/02-strings.xml index d9b00e1dca5b..1b4bd13fce37 100644 --- a/AnkiDroid/src/main/res/values-fy/02-strings.xml +++ b/AnkiDroid/src/main/res/values-fy/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Antwurd - Kaart - Set - Note - Fraach - Skaaimerken - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-ga/02-strings.xml b/AnkiDroid/src/main/res/values-ga/02-strings.xml index 97efe50f2a82..b5bb184d4361 100644 --- a/AnkiDroid/src/main/res/values-ga/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ga/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-gl/02-strings.xml b/AnkiDroid/src/main/res/values-gl/02-strings.xml index 969f97f10d50..613e5124ebe5 100644 --- a/AnkiDroid/src/main/res/values-gl/02-strings.xml +++ b/AnkiDroid/src/main/res/values-gl/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Pregunta - Campo de ordenación - - - Resposta - Cartón - Baralla - Nota - Pregunta - Etiquetas - Erros - Revisións - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-got/02-strings.xml b/AnkiDroid/src/main/res/values-got/02-strings.xml index abb28bffb425..32006428df5e 100644 --- a/AnkiDroid/src/main/res/values-got/02-strings.xml +++ b/AnkiDroid/src/main/res/values-got/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Sokns - Sort field - - - Andahafts - Karta - Wiko - Meleins - Bida - Sokeiniwaurda - Lapses - Domeinos - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-gu/02-strings.xml b/AnkiDroid/src/main/res/values-gu/02-strings.xml index 4824ac23d6ab..d1fc1f9f42d5 100644 --- a/AnkiDroid/src/main/res/values-gu/02-strings.xml +++ b/AnkiDroid/src/main/res/values-gu/02-strings.xml @@ -80,27 +80,6 @@ જીવલેણ ભૂલ: WebView રેન્ડરર ક્રેશ થયું. કારણ: %s સિસ્ટમ વેબ વ્યૂ રેન્ડરિંગ નિષ્ફળતા સિસ્ટમ WebView કાર્ડ \'%1$s\' રેન્ડર કરવામાં નિષ્ફળ થયું.\n %2$s - - - પ્રશ્ન - સૉર્ટ ક્ષેત્ર - - - જવાબ આપો - કાર્ડ - તૂતક - નૉૅધ - પ્રશ્ન - ટૅગ્સ - ક્ષતિઓ - સમીક્ષાઓ - અંતરાલ - સરળતા - બાકી - કાર્ડ સંશોધિત - બનાવ્યું - નોંધ સંશોધિત - ધ્વજ આજની નવી કાર્ડ મર્યાદામાં ફેરફાર કરો diff --git a/AnkiDroid/src/main/res/values-heb/02-strings.xml b/AnkiDroid/src/main/res/values-heb/02-strings.xml index 76e907ca3acd..29c959141230 100644 --- a/AnkiDroid/src/main/res/values-heb/02-strings.xml +++ b/AnkiDroid/src/main/res/values-heb/02-strings.xml @@ -80,27 +80,6 @@ שגיאה קריטית: הדמיית ה WebView קרסה. הסיבה: %s נכשלה הדמיית WebView של המערכת. מנוע התצוגה נכשל להציג את הכרטיס: %1$s. \n %2$s - - - שאלה - מיין שדה - - - תשובה - כרטיס - חפיסה - פתק - שאלה - תגים - מעידות - סקירות - מרווח זמן - קלות - תזמון - כרטיס השתנה - נוצר - רשומה השתנתה - דגלים שינוי מגבלת קלפים חדשים להיום diff --git a/AnkiDroid/src/main/res/values-hi/02-strings.xml b/AnkiDroid/src/main/res/values-hi/02-strings.xml index c9cf41d9ca12..414ec16233bf 100644 --- a/AnkiDroid/src/main/res/values-hi/02-strings.xml +++ b/AnkiDroid/src/main/res/values-hi/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView रेंडरर क्रैश हो गया। कारण: %s सिस्टम WebView रेंडरिंग विफलता सिस्टम WebView कार्ड रेंडर करने में विफल रहा \'%1$s\'.\n %2$s - - - प्रश्न - सॉर्ट फ़ील्ड - - - उत्तर - पत्ता - डेक - नोट - प्रश्न - टैग - चूक - समीक्षाएँ - अंतराल - आसानी - देय - कार्ड संशोधित किया गया - बनाया गया - नोट संशोधित किया गया - झंडे आज की नई कार्ड सीमा को संशोधित करें diff --git a/AnkiDroid/src/main/res/values-hr/02-strings.xml b/AnkiDroid/src/main/res/values-hr/02-strings.xml index 8ad9c9f98526..fc3c8782f7f2 100644 --- a/AnkiDroid/src/main/res/values-hr/02-strings.xml +++ b/AnkiDroid/src/main/res/values-hr/02-strings.xml @@ -80,27 +80,6 @@ Pogreška: Webview se srušio. Razlog: %s Sistemski WebView render greška. System WebView failed to render card \'%1$s\'.\n %2$s - - - Pitanje - Polje za sortiranje - - - Odgovor - Karta - Špil - Bilješka - Pitanje - Oznake - Greške - Pregledi - Interval - Ublažavanje - Istek - Card Modified - Kreirano - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-hu/02-strings.xml b/AnkiDroid/src/main/res/values-hu/02-strings.xml index 0dca68d54f64..6ab9797375af 100644 --- a/AnkiDroid/src/main/res/values-hu/02-strings.xml +++ b/AnkiDroid/src/main/res/values-hu/02-strings.xml @@ -80,27 +80,6 @@ Végzetes Hiba: a WebView megjelenítő összeomlott. Hiba oka: %s Webview Rendszer Megjenítői Hiba A WebView rendszer nem tudta megjeleníteni a \'%1$s\' kártyát.\n %2$s - - - Kérdés - Rendezési mező - - - Válasz - Kártya - Pakli neve - Jegyzettípus neve - Kérdés - Címkék - Elfelejtések száma - Ismétlések száma - Intervallum - Nehézség - Határidő - A kártya módosítva lett - Létrehozva - A jegyzet módosítva lett - Zászlók Módosítsa a mai új kártyakorlátot diff --git a/AnkiDroid/src/main/res/values-hy/02-strings.xml b/AnkiDroid/src/main/res/values-hy/02-strings.xml index 68327edddbce..85416628cafe 100644 --- a/AnkiDroid/src/main/res/values-hy/02-strings.xml +++ b/AnkiDroid/src/main/res/values-hy/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Հարց - Տեսակավորման դաշտ - - - Պատասխան - Քարտ - Կապուկ - Գրառում - Հարց - Պիտակներ - Մոռացված - Կրկնություններ - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-ind/02-strings.xml b/AnkiDroid/src/main/res/values-ind/02-strings.xml index b1b04aa5f8ac..50f343d9ac75 100644 --- a/AnkiDroid/src/main/res/values-ind/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ind/02-strings.xml @@ -80,27 +80,6 @@ Galat Fatal: Perender WebView mogok. Sebab: %s Sistem WebView Gagal Merender Sistem WebView gagal merender kartu \'%1$s\'.\n %2$s - - - Pertanyaan - Urutkan bidang - - - Jawaban - Kartu - Dek - Catatan - Pertanyaan - Tag - Kelupaan - Ulasan - Interval - Renggang - Jatuh tempo - Kartu diubah - Dibuat - Catatan diubah - Bendera Ubah batas kartu baru hari ini diff --git a/AnkiDroid/src/main/res/values-is/02-strings.xml b/AnkiDroid/src/main/res/values-is/02-strings.xml index f36cc4a2c47e..f7d2d304f631 100644 --- a/AnkiDroid/src/main/res/values-is/02-strings.xml +++ b/AnkiDroid/src/main/res/values-is/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-it/02-strings.xml b/AnkiDroid/src/main/res/values-it/02-strings.xml index ae741fae072c..42c600e25506 100644 --- a/AnkiDroid/src/main/res/values-it/02-strings.xml +++ b/AnkiDroid/src/main/res/values-it/02-strings.xml @@ -80,27 +80,6 @@ Errore fatale: il renderer WebView si è blocatto. Causa: %s Errore di restituzione grafica del sistema WebView La WebView sistema non è riuscita a rendere la carta «%1$s».\n %2$s - - - Domanda - Ordina per - - - Risposta - Carta - Mazzo - Nota - Domanda - Etichette - Errori - Ripetizioni - Intervallo - Facilità - Da ripetere - Carta modificata - Creato - Nota modificata - Contrassegni Modifica il limite odierno di nuove carte diff --git a/AnkiDroid/src/main/res/values-iw/02-strings.xml b/AnkiDroid/src/main/res/values-iw/02-strings.xml index 76e907ca3acd..29c959141230 100644 --- a/AnkiDroid/src/main/res/values-iw/02-strings.xml +++ b/AnkiDroid/src/main/res/values-iw/02-strings.xml @@ -80,27 +80,6 @@ שגיאה קריטית: הדמיית ה WebView קרסה. הסיבה: %s נכשלה הדמיית WebView של המערכת. מנוע התצוגה נכשל להציג את הכרטיס: %1$s. \n %2$s - - - שאלה - מיין שדה - - - תשובה - כרטיס - חפיסה - פתק - שאלה - תגים - מעידות - סקירות - מרווח זמן - קלות - תזמון - כרטיס השתנה - נוצר - רשומה השתנתה - דגלים שינוי מגבלת קלפים חדשים להיום diff --git a/AnkiDroid/src/main/res/values-ja/01-core.xml b/AnkiDroid/src/main/res/values-ja/01-core.xml index d9e5883d54ab..fe1c84cbed70 100644 --- a/AnkiDroid/src/main/res/values-ja/01-core.xml +++ b/AnkiDroid/src/main/res/values-ja/01-core.xml @@ -101,15 +101,15 @@ 休止 ノートを削除 フラグ - Rename flags + フラグの名前を変更 カードにフラグを付ける タグを編集 このカードの元となるノートを削除してもよろしいですか? 同じノートから作られたカード(例:裏表反転カード)があれば、それらもすべて削除されます。\n%s %1$s で検索 ノートにマークを付ける ノートのマークをはずす - Enable voice playback - Disable voice playback + 発音チェック機能をオン + 発音チェック機能をオフ デッキを新規作成 フィルターデッキを作成 AnkiDroidディレクトリにアクセスできません diff --git a/AnkiDroid/src/main/res/values-ja/02-strings.xml b/AnkiDroid/src/main/res/values-ja/02-strings.xml index 47d599a35cc6..7fcf9991d439 100644 --- a/AnkiDroid/src/main/res/values-ja/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ja/02-strings.xml @@ -80,27 +80,6 @@ 重大なエラー: WebViewレンダラーがクラッシュしました。原因: %s システムのWebViewのレンダリング失敗 AndroidシステムのWebViewがカード \'%1$s\' のレンダリングに失敗しました。\n %2$s - - - 質問 - ソートフィールド - - - 解答 - カードタイプ - デッキ - ノートタイプ - 質問 - タグ - 復習での忘却回数 - 学習回数 - 間隔 - 易しさ - 期日 - カード編集日 - 作成日 - ノート編集日 - フラグ 今日の新規カード上限を変更 diff --git a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml index ecf2cb3ea625..5c85a3e3f415 100644 --- a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml @@ -250,5 +250,5 @@ 「AndroidシステムのWebView 」(または「Android System WebView」)が古くなっています。いくつかの機能が正しく動作しません。更新してください。\n\nインストールされているバージョン: %1$d\n最低限必要なバージョン: %2$d - Confirm all changes before saving + 編集中のフラグがあります。保存する前に編集を終了してください。 diff --git a/AnkiDroid/src/main/res/values-jv/02-strings.xml b/AnkiDroid/src/main/res/values-jv/02-strings.xml index a307929ef051..a883fa9ef733 100644 --- a/AnkiDroid/src/main/res/values-jv/02-strings.xml +++ b/AnkiDroid/src/main/res/values-jv/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Pertanyaan - Bidang sortir - - - Menjawab - Kartu - Menjawab - Catatan - Pertanyaan - Tag - Lapisan - Ulasan - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-ka/02-strings.xml b/AnkiDroid/src/main/res/values-ka/02-strings.xml index 1c4c61b40019..c1d6f6f68d9f 100644 --- a/AnkiDroid/src/main/res/values-ka/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ka/02-strings.xml @@ -80,27 +80,6 @@ ფატალური შეცდომა: WebView მიმღები ავარიულად გაითიშა. მიზეზი: %s შეცდომა WebView სისტემის დამუშავებისას WebView სისტემამ ვერ დაამუშავა ბარათი „%1$s“.\n %2$s - - - კითხვა - სორტირების ველი - - - პასუხი - ბარათი - დასტა - შენიშვნა - კითხვა - იარლიყები - გადავიწყება - გადახედვა - შუალედი - სიმარტივე - სასწავლო - ბარათის მოდიფიკაცია - შექმნილია - შენიშვნის მოდიფიკაცია - დროშები დღეის ახალი ბარათების ლიმიტის შეცვლა diff --git a/AnkiDroid/src/main/res/values-kk/02-strings.xml b/AnkiDroid/src/main/res/values-kk/02-strings.xml index f36cc4a2c47e..f7d2d304f631 100644 --- a/AnkiDroid/src/main/res/values-kk/02-strings.xml +++ b/AnkiDroid/src/main/res/values-kk/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-km/02-strings.xml b/AnkiDroid/src/main/res/values-km/02-strings.xml index e71e540a3f1c..2050fc037c6b 100644 --- a/AnkiDroid/src/main/res/values-km/02-strings.xml +++ b/AnkiDroid/src/main/res/values-km/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-kn/02-strings.xml b/AnkiDroid/src/main/res/values-kn/02-strings.xml index 37844e07c608..27da92c8d088 100644 --- a/AnkiDroid/src/main/res/values-kn/02-strings.xml +++ b/AnkiDroid/src/main/res/values-kn/02-strings.xml @@ -80,27 +80,6 @@ ಮಾರಕ ದೋಷ: ವೆಬ್‌ವೀಕ್ಷಣೆ ರೆಂಡರರ್ ಕ್ರ್ಯಾಶ್ ಆಗಿದೆ. ಕಾರಣ:%s ಸಿಸ್ಟಮ್ ವೆಬ್‌ವೀಕ್ಷಣೆ ರೆಂಡರಿಂಗ್ ವಿಫಲತೆ \'%1$s\' ಕಾರ್ಡ್ ಅನ್ನು ನಿರೂಪಿಸಲು ಸಿಸ್ಟಮ್ ವೆಬ್‌ವೀಕ್ಷಣೆ ವಿಫಲವಾಗಿದೆ.\n %2$s - - - ಪ್ರಶ್ನೆಗಳು - ವಿಂಗಡಣೆ ಕ್ಷೇತ್ರ - - - ಉತ್ತರಿಸಿ - ಕಾರ್ಡ್ - ಡೆಕ್ - ಟಿಪ್ಪಣಿ - ಪ್ರಶ್ನೆಗಳು - ಟ್ಯಾಗ್ಗಳು - ಲ್ಯಾಪ್ಸ್ - ವಿಮರ್ಶೆಗಳು - ಮಧ್ಯಂತರ - ಸರಾಗ - ಬಾಕಿ - ಕಾರ್ಡ್ ಮಾರ್ಪಡಿಸಲಾಗಿದೆ - ರಚಿಸಲಾಗಿದೆ - ಟಿಪ್ಪಣಿ ಮಾರ್ಪಡಿಸಲಾಗಿದೆ - ಧ್ವಜಗಳು ಇಂದಿನ ಹೊಸ ಕಾರ್ಡ್ ಮಿತಿಯನ್ನು ಮಾರ್ಪಡಿಸಿ diff --git a/AnkiDroid/src/main/res/values-ko/02-strings.xml b/AnkiDroid/src/main/res/values-ko/02-strings.xml index 69b70b72f41b..4b271b8c6b1e 100644 --- a/AnkiDroid/src/main/res/values-ko/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ko/02-strings.xml @@ -81,27 +81,6 @@ WebView 렌더링이 실패했습니다. WebView가 \'%1$s\' 카드를 렌더링하지 못했습니다. %2$s - - - 질문 - 필드 정렬 - - - 정답 - 카드 - - 노트 - 문제 - 태그 - 오답 횟수 - 복습 - 시간 간격 - 수월함 - 예정 - 카드 수정일 - 작성한 날짜 - 노트 편집일 - 플래그 오늘의 새로운 카드 학습량 늘리기 diff --git a/AnkiDroid/src/main/res/values-ku/02-strings.xml b/AnkiDroid/src/main/res/values-ku/02-strings.xml index 069cbabf174e..6a7e66dfb923 100644 --- a/AnkiDroid/src/main/res/values-ku/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ku/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Bersiv - Card - Deck - Note - Pirs - Etîket - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-ky/02-strings.xml b/AnkiDroid/src/main/res/values-ky/02-strings.xml index f36cc4a2c47e..f7d2d304f631 100644 --- a/AnkiDroid/src/main/res/values-ky/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ky/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-lt/02-strings.xml b/AnkiDroid/src/main/res/values-lt/02-strings.xml index 30fae8b43a1c..e46c24879964 100644 --- a/AnkiDroid/src/main/res/values-lt/02-strings.xml +++ b/AnkiDroid/src/main/res/values-lt/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Klausimas - Rūšiavimo laukas - - - Atsakymas - Kortelė - Rinkinys - Užrašas - Klausimas - Žymos - Dažnai užmirštamos - Peržiūros - Intervalas - Ease - Due - Kortelė pakeista - Sukurta - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-lv/02-strings.xml b/AnkiDroid/src/main/res/values-lv/02-strings.xml index 8a5bc42c4d3e..d1ab2eaef21f 100644 --- a/AnkiDroid/src/main/res/values-lv/02-strings.xml +++ b/AnkiDroid/src/main/res/values-lv/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-mk/02-strings.xml b/AnkiDroid/src/main/res/values-mk/02-strings.xml index 74ec64bd8f8a..824fa9db36cf 100644 --- a/AnkiDroid/src/main/res/values-mk/02-strings.xml +++ b/AnkiDroid/src/main/res/values-mk/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Прашање - Сортирај поле - - - Одговори - Картичка - Коло - Забелешка - Прашање - Тагови - Пропусти - Прегледи - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-ml/02-strings.xml b/AnkiDroid/src/main/res/values-ml/02-strings.xml index 7c99593b72c3..0a70accdbc12 100644 --- a/AnkiDroid/src/main/res/values-ml/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ml/02-strings.xml @@ -80,27 +80,6 @@ മാരകമായ പിശക്: വെബ്‌വ്യൂ റെൻഡറർ തകർന്നു. കാരണം:%s സിസ്റ്റം വെബ്‌വ്യൂ റെൻഡറിംഗ് പരാജയം \'%1$s\' കാർഡ് റെൻഡർ ചെയ്യുന്നതിൽ സിസ്റ്റം വെബ്‌വ്യൂ പരാജയപ്പെട്ടു. \n%2$s - - - ചോദ്യം - ഫീൽഡ് അടുക്കുക - - - ഉത്തരം - കാർഡ് - ഡെക്ക് - കുറിപ്പ് - ചോദ്യം - ടാഗുകൾ - ലാപ്‌സുകൾ - അവലോകനങ്ങൾ - ഇടവേള - അനായാസം - കാരണം - കാർഡ് പരിഷ്‌ക്കരിച്ചു - സൃഷ്ടിച്ചു - കുറിപ്പ് പരിഷ്‌ക്കരിച്ചു - Flags ഇന്നത്തെ പുതിയ കാർഡ് പരിധി പരിഷ്‌ക്കരിക്കുക diff --git a/AnkiDroid/src/main/res/values-mn/02-strings.xml b/AnkiDroid/src/main/res/values-mn/02-strings.xml index 9a578b98cbe9..f6b25554b91d 100644 --- a/AnkiDroid/src/main/res/values-mn/02-strings.xml +++ b/AnkiDroid/src/main/res/values-mn/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Асуулт - Хэсгийг эрэмбэлэх - - - Хариулт - Картаар - Багц - Тэмдэглэл - Асуулт - Шошгууд - Явц - Үнэлгээний тоогоор - Завсар - Хэцүү, амраар - Дуусах хугацаагаар - Картыг өөрчилсөн хугацаагаар нь - Үүсгэснээр нь - Өөрчилсөн тэмдэглэл - Дарцагнууд Өнөөдрийн судлах картны тоог өөрчлөх diff --git a/AnkiDroid/src/main/res/values-mr/02-strings.xml b/AnkiDroid/src/main/res/values-mr/02-strings.xml index 1cae73acefc6..97ae543ba371 100644 --- a/AnkiDroid/src/main/res/values-mr/02-strings.xml +++ b/AnkiDroid/src/main/res/values-mr/02-strings.xml @@ -80,27 +80,6 @@ गंभीर त्रुटी: वेबव्यू प्रस्तुतकर्ता क्रॅश झाला. कारणः%s सिस्टम वेबव्यू प्रस्तुत करणे अयशस्वी सिस्टम \'वेबव्यू\' \'%1$s\' कार्ड प्रस्तुत करण्यात अयशस्वी. \ N%2$s - - - Praśna - Kramavārī lāvā phīlḍa - - - Uttara dyā - Kārḍa - Ḍēka - Ṭīpa - Praśna - Ṭĕgja - Lapses - Punarāvalōkanē - मध्यांतर - सहजता - देय - कार्ड सुधारित - तयार केले - टीप सुधारित - ध्वज आजची नवीन कार्ड मर्यादा सुधारित करा diff --git a/AnkiDroid/src/main/res/values-ms/02-strings.xml b/AnkiDroid/src/main/res/values-ms/02-strings.xml index 5367386cad6e..be5b22d0ab4b 100644 --- a/AnkiDroid/src/main/res/values-ms/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ms/02-strings.xml @@ -80,27 +80,6 @@ Ralat Maut: Pemapar WebView ranap. Punca: %s Kegagalan Pemaparan Sistem WebView WebView Sistem gagal memapar kad \'%1$s\'.\n %2$s - - - Soalan - Susun medan - - - Jawapan - Kad - Dek - Nota - Soalan - Tag - Cuaian - Semakan - Selang - Longgaran - Tunggak - Kad diubah - Dicipta - Nota diubah - Tanda Ubah had kad baru hari ini diff --git a/AnkiDroid/src/main/res/values-my/02-strings.xml b/AnkiDroid/src/main/res/values-my/02-strings.xml index e092ffe8f08c..516d67119845 100644 --- a/AnkiDroid/src/main/res/values-my/02-strings.xml +++ b/AnkiDroid/src/main/res/values-my/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-nl/02-strings.xml b/AnkiDroid/src/main/res/values-nl/02-strings.xml index 87a2f1d233fa..8a9d4432205d 100644 --- a/AnkiDroid/src/main/res/values-nl/02-strings.xml +++ b/AnkiDroid/src/main/res/values-nl/02-strings.xml @@ -80,27 +80,6 @@ Fatale fout: WebView renderer is gecrasht. Oorzaak: %s Systeem WebView Rendering Mislukking. Systeem WebView kon de kaart \'%1$s\' niet renderen.\n%2$s - - - Vraag - Sorteerveld - - - Antwoord - Kaart - Set - Memo - Vraag - Labels - Missers - Overhoringen - Interval - Gemak - Deadline - Kaart Gewijzigd - Gemaakt - Memo gewijzigd - Vlaggen Nieuwe kaartenlimiet voor vandaag wijzigen diff --git a/AnkiDroid/src/main/res/values-nn/02-strings.xml b/AnkiDroid/src/main/res/values-nn/02-strings.xml index e2ec28a929fd..376ce359a5b6 100644 --- a/AnkiDroid/src/main/res/values-nn/02-strings.xml +++ b/AnkiDroid/src/main/res/values-nn/02-strings.xml @@ -80,27 +80,6 @@ Kritisk feil: WebView-avspiller krasjet. Årsak: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Spørsmål - Sorter feltet - - - Svar - Kort - Kortleik - Notat - Spørsmål - Etiketter - Feilsvar - Repetisjonar - Intervall - Lette - Forfaller - Kort endra - Laga - Notat endret - Flagg Endre grensa for nye kort i dag diff --git a/AnkiDroid/src/main/res/values-no/02-strings.xml b/AnkiDroid/src/main/res/values-no/02-strings.xml index 0052484bfd96..c26859880003 100644 --- a/AnkiDroid/src/main/res/values-no/02-strings.xml +++ b/AnkiDroid/src/main/res/values-no/02-strings.xml @@ -80,27 +80,6 @@ Kritisk feil: WebView-avspiller krasjet. Årsak: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Spørsmål - Sorter feltet - - - Svar - Kort - Kortstokk - Notat - Spørsmål - Etiketter - Feilsvar - Repetisjoner - Intervall - Ease - Forfaller - Kort endret - Opprettet - Notat endret - Flags Endre dagens nye kortgrense diff --git a/AnkiDroid/src/main/res/values-or/02-strings.xml b/AnkiDroid/src/main/res/values-or/02-strings.xml index a1c0e409476d..a03a8472c690 100644 --- a/AnkiDroid/src/main/res/values-or/02-strings.xml +++ b/AnkiDroid/src/main/res/values-or/02-strings.xml @@ -80,27 +80,6 @@ ସାଂଘାତିକ ତ୍ରୁଟି: WebView ପ୍ରସ୍ତୁତକର୍ତ୍ତା ଦୁର୍ଘଟଣାଗ୍ରସ୍ତ ହୋଇଛି। କାରଣ: %s ସିଷ୍ଟମର WebView ପ୍ରସ୍ତୁତକର୍ତ୍ତାରେ ବିଫଳତା ସିଷ୍ଟମ୍ WebView \'%1$s\' ପତ୍ର କୁ ପ୍ରସ୍ତୁତ କଲାନାହିଁ।\n %2$s - - - ପ୍ରଶ୍ନ - ସଜାଇବା କ୍ଷେତ୍ର - - - ଉତ୍ତର - ପତ୍ର - ତାସଖଣ୍ଡ - ନୋଟ୍ - ପ୍ରଶ୍ନ - ଟ୍ୟାଗ ସମୂହ - ଲାପ୍ସ ସଂଖ୍ୟା - ସମୀକ୍ଷା - ଅନ୍ତରାଳ - ସହଜତା - ବାକି - ପତ୍ର ସଂଶୋଧିତ - ତିଆରି କରାଯାଇଅଛି - ନୋଟ୍ ସଂଶୋଧିତ - ପତାକା ଆଜିର ନୂଆ ପତ୍ରସଂଖ୍ୟା ସୀମା ସଂଶୋଧନ diff --git a/AnkiDroid/src/main/res/values-pa/02-strings.xml b/AnkiDroid/src/main/res/values-pa/02-strings.xml index f36cc4a2c47e..f7d2d304f631 100644 --- a/AnkiDroid/src/main/res/values-pa/02-strings.xml +++ b/AnkiDroid/src/main/res/values-pa/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-pl/02-strings.xml b/AnkiDroid/src/main/res/values-pl/02-strings.xml index 433a513e63a1..70779466ddaf 100644 --- a/AnkiDroid/src/main/res/values-pl/02-strings.xml +++ b/AnkiDroid/src/main/res/values-pl/02-strings.xml @@ -80,27 +80,6 @@ Błąd krytyczny: awaria renderowania WebView. Przyczyna: %s Błąd renderowania WebView systemu System WebView nie potrafił wyrenderować karty \'%1$s\'.\n %2$s - - - Pytanie - Sortowanie według pola - - - Odpowiedź - Karta - Talia - Notka - Pytanie - Tagi - Pomyłki - Powtórki - Przerwa - Łatwość - Do przejrzenia - Zmodyfikowano kartę - Stworzona - Zmodyfikowano notatkę - Flagi Zmień dzisiejszy limit nowych kart diff --git a/AnkiDroid/src/main/res/values-pt-rBR/02-strings.xml b/AnkiDroid/src/main/res/values-pt-rBR/02-strings.xml index 6a5b6310b810..5b9971b3a854 100644 --- a/AnkiDroid/src/main/res/values-pt-rBR/02-strings.xml +++ b/AnkiDroid/src/main/res/values-pt-rBR/02-strings.xml @@ -80,27 +80,6 @@ Erro Fatal: WebView renderer crashou. Causa: %s Falha no System Rendering WebView O System WebView falhou ao renderizar o card \'%1$s\'.\n %2$s - - - Questão - Classificar campos - - - Resposta - Card - Baralho - Nota - Questão - Tags - Falhas - Revisões - Intervalo - Retenção - Pendente - Card Modificado - Criado - Nota modificada - Bandeiras Modificar o limite de novos cards para hoje diff --git a/AnkiDroid/src/main/res/values-pt-rPT/02-strings.xml b/AnkiDroid/src/main/res/values-pt-rPT/02-strings.xml index 065696b2ed1a..6938503105e1 100644 --- a/AnkiDroid/src/main/res/values-pt-rPT/02-strings.xml +++ b/AnkiDroid/src/main/res/values-pt-rPT/02-strings.xml @@ -80,27 +80,6 @@ Erro fatal: o processador do \"WebView\" falhou. Causa: %s Falha no processamento do \"WebView\" O \"WebView\" de sistema falhou no processamento da ficha \'%1$s\'.\n %2$s - - - Pergunta - Ordenar campo - - - Resposta - Ficha - Baralho - Nota - Pergunta - Etiquetas - Falhas - Revisões - Intervalo - Facilidade - Data limite - Ficha modificada - Criada - Data de Modificação da Nota - Sinalização Modificar o limite de novas fichas para hoje diff --git a/AnkiDroid/src/main/res/values-ro/02-strings.xml b/AnkiDroid/src/main/res/values-ro/02-strings.xml index db0d0a864d79..975f91405a1f 100644 --- a/AnkiDroid/src/main/res/values-ro/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ro/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Răspuns - Card - Pachet - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-ru/02-strings.xml b/AnkiDroid/src/main/res/values-ru/02-strings.xml index 2c10d2ab8628..40ae83486da5 100644 --- a/AnkiDroid/src/main/res/values-ru/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ru/02-strings.xml @@ -80,27 +80,6 @@ Критическая ошибка: WebView завершился. Причина: %s Сбой системного WebView Системному WebView не удалось отрисовать карточку «%1$s».\n %2$s - - - Вопрос - Поле сортировки - - - Ответ - Карточка - Колода - Тип записи - Вопрос - Метки - Забытые - Повторения - Интервал - Лёгкость - Срок - Карточка изменена - Создано - Запись изменена - Флажки Увеличить лимит новых diff --git a/AnkiDroid/src/main/res/values-sat/02-strings.xml b/AnkiDroid/src/main/res/values-sat/02-strings.xml index cf4417ac2a57..097d56e6cc9a 100644 --- a/AnkiDroid/src/main/res/values-sat/02-strings.xml +++ b/AnkiDroid/src/main/res/values-sat/02-strings.xml @@ -80,27 +80,6 @@ Fatal ᱵᱷᱩᱞ: WebView ᱨᱮᱱᱰᱚᱨᱚᱨ ᱠᱨᱟᱥ ᱮᱱᱟ ᱾ ᱠᱟᱨᱚᱬ:%s ᱥᱤᱥᱴᱚᱢ WebView ᱨᱮᱱᱰᱚᱨᱤᱝ ᱯᱷᱮᱞ ᱮᱱᱟ ᱥᱤᱥᱴᱚᱢ WebView ᱠᱟᱨᱰ ᱨᱮᱱᱰᱚᱨᱤᱝ ᱡᱚᱠᱷᱟᱜ ᱯᱷᱮᱞ ᱮᱱᱟ \'%1$s\'.\n%2$s - - - ᱯᱚᱨᱥᱚᱱ - ᱡᱟᱭᱛᱟ ᱥᱚᱨᱟᱴ ᱢᱮ - - - ᱛᱮᱞᱟ - ᱠᱟᱰ - ᱰᱮᱠ - ᱠᱷᱟᱴᱚ ᱵᱤᱪᱟᱹᱨ - ᱯᱚᱨᱥᱚᱱ - ᱴᱮᱜᱥ - ᱞᱮᱯᱥ - ᱥᱚᱢᱤᱠᱷᱭᱟ - ᱚᱸᱛᱨᱟᱞ - ᱥᱚᱦᱚᱡ - ᱮᱢᱚᱜ ᱥᱚᱢᱚᱭ - ᱠᱟᱰ ᱵᱚᱫᱚᱞᱮᱱᱟ - ᱛᱮᱭᱟᱨ ᱮᱱᱟ - ᱠᱷᱟᱴᱚ ᱵᱤᱪᱟᱹᱨ ᱵᱚᱫᱚᱞᱮᱱᱟ - ᱯᱚᱛᱠᱟ ᱠᱚ ᱛᱮᱦᱮᱧᱼᱟᱜ ᱱᱟᱶᱟ ᱠᱟᱰ ᱞᱤᱢᱤᱴ ᱵᱚᱫᱚᱞ ᱢᱮ diff --git a/AnkiDroid/src/main/res/values-sc/02-strings.xml b/AnkiDroid/src/main/res/values-sc/02-strings.xml index 53a543c216e9..778c98088a96 100644 --- a/AnkiDroid/src/main/res/values-sc/02-strings.xml +++ b/AnkiDroid/src/main/res/values-sc/02-strings.xml @@ -81,27 +81,6 @@ Fallimentu de sa renderizatzione WebView de sistema Su renderizadore WebView de sistema no est resèssidu a renderizare sa carta \'%1$s\'.\n %2$s - - - Campu de ordinamentu - Pregunta - - - Carta - Matzu - Nota - Pregunta - Etichetas - Faddinas - Revisiones - I - Intervallu - Nota modificada - G - Fatzilidade - Creadu - Carta modificada - Banderas Modìfica su lìmite de cartas noas de oe diff --git a/AnkiDroid/src/main/res/values-sk/02-strings.xml b/AnkiDroid/src/main/res/values-sk/02-strings.xml index 72942c65b793..900c8ac04f78 100644 --- a/AnkiDroid/src/main/res/values-sk/02-strings.xml +++ b/AnkiDroid/src/main/res/values-sk/02-strings.xml @@ -80,27 +80,6 @@ Fatálna chyba: WebView renderovanie zlyhalo. Príčina: %s Zlyhanie systému WebView renderovania Zobrazenie kartičky systémom WebView zlyhalo \'%1$s\'.\n %2$s - - - Otázka - Triediace pole - - - Odpoveď - Kartička - Balíček - Poznámka - Otázka - Štítky - Zabudnutia - Opakovania - Interval - Ľahkosť - Na preskúšanie - Kartička modifikovaná - Vytvorené - Poznámka modifikovaná - Vlajky Modifikovať dnešný limit nových kartičiek diff --git a/AnkiDroid/src/main/res/values-sl/02-strings.xml b/AnkiDroid/src/main/res/values-sl/02-strings.xml index f00cf5afc778..07e7e90a9bf0 100644 --- a/AnkiDroid/src/main/res/values-sl/02-strings.xml +++ b/AnkiDroid/src/main/res/values-sl/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Vprašanje - Polje za razvrščanje - - - Odgovor - Kartica - Komplet - Zapisek - Vprašanje - Oznake - Spodrsljaji - Pregledi - Interval - Ease - Due - Spremenjena kartica - Ustvarjeno - Spremenjen zapisek - Oznaka Povečaj omejitev novih kartic za danes diff --git a/AnkiDroid/src/main/res/values-sq/02-strings.xml b/AnkiDroid/src/main/res/values-sq/02-strings.xml index d942582a73dd..557b59fdd3bd 100644 --- a/AnkiDroid/src/main/res/values-sq/02-strings.xml +++ b/AnkiDroid/src/main/res/values-sq/02-strings.xml @@ -80,27 +80,6 @@ Gabim fatal: Renderer WebView u rrëzua. Shkaku: %s Dështimi i paraqitjes së shikimit në ueb të sistemit Sistemi WebView dështoi në paraqitjen e kartës \'%1$s\'.\n %2$s - - - Pyetje - Fusha e renditjes - - - Përgjigju - Kartelë - Kuvertë - shënim - Pyetje - Etiketa - Gabimet - Shqyrtime - Intervali - Lehtësi - Pritet - Karta e modifikuar - Krijuar - Shënimi i modifikuar - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-sr/02-strings.xml b/AnkiDroid/src/main/res/values-sr/02-strings.xml index 1a41795b87ac..e44bc746a318 100644 --- a/AnkiDroid/src/main/res/values-sr/02-strings.xml +++ b/AnkiDroid/src/main/res/values-sr/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Питање - Поље за сортирање - - - Одговор - Картица - Шпил - Белешка - Питање - Ознаке - Промашаји - Понављања - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-ss/02-strings.xml b/AnkiDroid/src/main/res/values-ss/02-strings.xml index f36cc4a2c47e..f7d2d304f631 100644 --- a/AnkiDroid/src/main/res/values-ss/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ss/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-sv/02-strings.xml b/AnkiDroid/src/main/res/values-sv/02-strings.xml index ddf1a2fa6ea0..ff41050aa71d 100644 --- a/AnkiDroid/src/main/res/values-sv/02-strings.xml +++ b/AnkiDroid/src/main/res/values-sv/02-strings.xml @@ -80,27 +80,6 @@ Kritiskt fel: WebViewern kraschade. Orsak: %s Systemfel hos WebViewern WebViewern kunde inte hämta kortet \'%1$s\'.\n %2$s - - - Fråga - Sortera fält - - - Svar - Kort - Kortlek - Not - Fråga - Etiketter - Felsvar - Repetitioner - Intervall - Lätthet - Förfallodatum - Kort ändrat - Skapad - Not ändrad - Flaggor Ändra dagens gräns för nya kort diff --git a/AnkiDroid/src/main/res/values-sw/02-strings.xml b/AnkiDroid/src/main/res/values-sw/02-strings.xml index f36cc4a2c47e..f7d2d304f631 100644 --- a/AnkiDroid/src/main/res/values-sw/02-strings.xml +++ b/AnkiDroid/src/main/res/values-sw/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-ta/02-strings.xml b/AnkiDroid/src/main/res/values-ta/02-strings.xml index f36cc4a2c47e..f7d2d304f631 100644 --- a/AnkiDroid/src/main/res/values-ta/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ta/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-te/02-strings.xml b/AnkiDroid/src/main/res/values-te/02-strings.xml index 473a9dbcca19..d03b3d95d822 100644 --- a/AnkiDroid/src/main/res/values-te/02-strings.xml +++ b/AnkiDroid/src/main/res/values-te/02-strings.xml @@ -80,27 +80,6 @@ ఘోరమైన లోపం: WebView రెండరర్ క్రాష్ అయింది. కారణం: %s సిస్టమ్ WebView రెండరింగ్ వైఫల్యం \'%1$s\' కార్డ్‌ని రెండర్ చేయడంలో సిస్టమ్ WebView విఫలమైంది.\n %2$s - - - ప్రశ్న - క్రమీకరించు ఫీల్డ్ - - - సమాధానం - కార్డ్ - డెక్ - గమనిక - ప్రశ్న - టాగ్లు - లాప్సెస్ - సమీక్షలు - విరామం - సులభంగా - ఎందుకంటే - కార్డ్ సవరించబడింది - సృష్టించబడింది - గమనిక సవరించబడింది - జెండాలు నేటి కొత్త కార్డ్ పరిమితిని సవరించండి diff --git a/AnkiDroid/src/main/res/values-tg/02-strings.xml b/AnkiDroid/src/main/res/values-tg/02-strings.xml index f36cc4a2c47e..f7d2d304f631 100644 --- a/AnkiDroid/src/main/res/values-tg/02-strings.xml +++ b/AnkiDroid/src/main/res/values-tg/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-tgl/02-strings.xml b/AnkiDroid/src/main/res/values-tgl/02-strings.xml index 39bb60a57eb2..812c78a7c618 100644 --- a/AnkiDroid/src/main/res/values-tgl/02-strings.xml +++ b/AnkiDroid/src/main/res/values-tgl/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Tanong - Pagsasaayos ng field - - - Sagot - Baraha - Deck - Paalala - Tanong - Mga tag - Mga pagkakamali - Balik-aral - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-th/02-strings.xml b/AnkiDroid/src/main/res/values-th/02-strings.xml index 8fdbec2e54be..956110eeb4e5 100644 --- a/AnkiDroid/src/main/res/values-th/02-strings.xml +++ b/AnkiDroid/src/main/res/values-th/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - คำถาม - Sort field - - - คำตอบ - การ์ด - Deck - โน้ต - Question - แท็ก - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-ti/02-strings.xml b/AnkiDroid/src/main/res/values-ti/02-strings.xml index f36cc4a2c47e..f7d2d304f631 100644 --- a/AnkiDroid/src/main/res/values-ti/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ti/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-tn/02-strings.xml b/AnkiDroid/src/main/res/values-tn/02-strings.xml index f36cc4a2c47e..f7d2d304f631 100644 --- a/AnkiDroid/src/main/res/values-tn/02-strings.xml +++ b/AnkiDroid/src/main/res/values-tn/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-tr/02-strings.xml b/AnkiDroid/src/main/res/values-tr/02-strings.xml index 2a460d6fdded..b533fdd8e204 100644 --- a/AnkiDroid/src/main/res/values-tr/02-strings.xml +++ b/AnkiDroid/src/main/res/values-tr/02-strings.xml @@ -80,27 +80,6 @@ Kritik Hata: WebView oluşturucusu çöktü. Neden: %s Sistem WebView Oluşturma Hatası Sistem WebView bu kartı işleyemedi: \'%1$s\'.\n %2$s - - - Soru - Alanı sırala - - - Cevap - Kart - Deste - Not - Soru - Etiketler - Yanlışlar - Çalışmalar - Aralık - Kolaylık - Vade - Kart Değiştirildi - Oluşturulma Tarihi - Değiştirilmiş Notlar - Bayraklar Bugünün yeni kart sınırını düzenle diff --git a/AnkiDroid/src/main/res/values-ts/02-strings.xml b/AnkiDroid/src/main/res/values-ts/02-strings.xml index f36cc4a2c47e..f7d2d304f631 100644 --- a/AnkiDroid/src/main/res/values-ts/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ts/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-tt/02-strings.xml b/AnkiDroid/src/main/res/values-tt/02-strings.xml index f8b24273a30b..4d2b2a982f1c 100644 --- a/AnkiDroid/src/main/res/values-tt/02-strings.xml +++ b/AnkiDroid/src/main/res/values-tt/02-strings.xml @@ -80,27 +80,6 @@ Критик хата: WebView ябылды. Сәбәбе: %s Система WebViewының хатасы Система WebViewы \'%1$s\' кәртен ача алмады.\n %2$s - - - Сорау - Сортлау аланы - - - Җәвап - Кәрт - Колода - Язу - Сорау - Тамгалар - Ялгышлар - Кабатлаулар - Интервал - Авырлык - Вакыт - Кәрт үзгәртелеше - Ясалган - Язу үзгәртелеше - Байраклар Бугенге кәрт лимитын үзгәртү diff --git a/AnkiDroid/src/main/res/values-uk/02-strings.xml b/AnkiDroid/src/main/res/values-uk/02-strings.xml index 38018ba70eda..669e7794fd72 100644 --- a/AnkiDroid/src/main/res/values-uk/02-strings.xml +++ b/AnkiDroid/src/main/res/values-uk/02-strings.xml @@ -80,27 +80,6 @@ Критична помилка WebView. Причина: %s Збій системного WebView Системою WebView не вдалося відобразити картку \'%1$s\'.\n %2$s - - - Запитання - Поле сортування - - - Відповідь - Картка - Колода - Запис - Запитання - Теги - Забуті - Повторення - Інтервал - Легкість - До перегляду - Картку змінено - Створено - Запис змінено - Прапорці Змінити сьогоднішній ліміт нових карток diff --git a/AnkiDroid/src/main/res/values-ur/02-strings.xml b/AnkiDroid/src/main/res/values-ur/02-strings.xml index 456159c0dcd0..2f7e74ab95a2 100644 --- a/AnkiDroid/src/main/res/values-ur/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ur/02-strings.xml @@ -80,27 +80,6 @@ مہلک خرابی: WebView پیش کنندہ کریش ہو گیا۔ وجہ: %s سسٹم ویب ویو رینڈرنگ میں ناکامی۔ سسٹم WebView کارڈ \'%1$s\' رینڈر کرنے میں ناکام رہا۔\n %2$s - - - سوال - ترتیب دیں فیلڈ - - - جواب - کارڈ - ڈیک - نوٹ - سوال - ٹیگز - لیپس - جائزے - وقفہ - آسانی - بقایا - کارڈ میں ترمیم کی گئی - بنایا - ترمیم شدہ نوٹ - جھنڈے آج کی نئی کارڈ کی حد میں ترمیم کریں۔ diff --git a/AnkiDroid/src/main/res/values-uz/02-strings.xml b/AnkiDroid/src/main/res/values-uz/02-strings.xml index 03b640ae1ad1..e27ad27713d1 100644 --- a/AnkiDroid/src/main/res/values-uz/02-strings.xml +++ b/AnkiDroid/src/main/res/values-uz/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-ve/02-strings.xml b/AnkiDroid/src/main/res/values-ve/02-strings.xml index f36cc4a2c47e..f7d2d304f631 100644 --- a/AnkiDroid/src/main/res/values-ve/02-strings.xml +++ b/AnkiDroid/src/main/res/values-ve/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-vi/02-strings.xml b/AnkiDroid/src/main/res/values-vi/02-strings.xml index cba9ddc0b8cc..f58d092f47fa 100644 --- a/AnkiDroid/src/main/res/values-vi/02-strings.xml +++ b/AnkiDroid/src/main/res/values-vi/02-strings.xml @@ -80,27 +80,6 @@ Lỗi nghiêm trọng: Trình kết xuất WebView bị lỗi. Nguyên nhân: %s Hệ thống hiển thị WebView không thành công Hệ thống WebView không thể hiển thị thẻ \'%1$s\'.\ n%2$s - - - Câu hỏi - Sắp xếp trường - - - Đáp án - Thẻ - Bộ thẻ - Ghi chú - Câu hỏi - Các đuôi - Lần sai - Lần ôn tập - Khoảng nghỉ - Độ khó - Hạn - Thẻ đã sửa đổi - Đã tạo - Ghi chú đã sửa đổi - Cờ Sửa đổi giới hạn thẻ mới của ngày hôm nay diff --git a/AnkiDroid/src/main/res/values-wo/02-strings.xml b/AnkiDroid/src/main/res/values-wo/02-strings.xml index e092ffe8f08c..516d67119845 100644 --- a/AnkiDroid/src/main/res/values-wo/02-strings.xml +++ b/AnkiDroid/src/main/res/values-wo/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-xh/02-strings.xml b/AnkiDroid/src/main/res/values-xh/02-strings.xml index f36cc4a2c47e..f7d2d304f631 100644 --- a/AnkiDroid/src/main/res/values-xh/02-strings.xml +++ b/AnkiDroid/src/main/res/values-xh/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-yue/02-strings.xml b/AnkiDroid/src/main/res/values-yue/02-strings.xml index 01735f458747..85f0c999847d 100644 --- a/AnkiDroid/src/main/res/values-yue/02-strings.xml +++ b/AnkiDroid/src/main/res/values-yue/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - 問題 - Sort field - - - 答案 - Card - Deck - 筆記 - 問題 - 標籤 - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit diff --git a/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml b/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml index cd1323543def..24decc36b0d4 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/01-core.xml @@ -108,8 +108,8 @@ 在%1$s中查找 标记笔记 取消标记 - Enable voice playback - Disable voice playback + 启用语音播放 + 禁用语音播放 创建牌组 创建筛选牌组 无法访问AnkiDroid目录 diff --git a/AnkiDroid/src/main/res/values-zh-rCN/02-strings.xml b/AnkiDroid/src/main/res/values-zh-rCN/02-strings.xml index 595cd377227f..cf0a948ccae1 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/02-strings.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/02-strings.xml @@ -80,27 +80,6 @@ 严重错误:WebView 渲染器崩溃。原因:%s 系统 WebView 渲染失败 系统 WebView 渲染卡片 “%1$s” 失败。\n %2$s - - - 问题 - 字段 - - - 答案 - 卡片 - 牌组 - 笔记 - 问题 - 标签 - 遗忘 - 复习 - 间隔 - 简易度 - 到期 - 卡片修改时间 - 卡片创建时间 - 笔记修改时间 - 旗标 修改今天的新卡片数量限制 diff --git a/AnkiDroid/src/main/res/values-zh-rTW/02-strings.xml b/AnkiDroid/src/main/res/values-zh-rTW/02-strings.xml index 44bb10447e21..ccf64ce83150 100644 --- a/AnkiDroid/src/main/res/values-zh-rTW/02-strings.xml +++ b/AnkiDroid/src/main/res/values-zh-rTW/02-strings.xml @@ -80,27 +80,6 @@ 致命錯誤:WebView 渲染器已崩潰。原因:%s 系統 WebView 渲染失敗 系統 WebView 渲染卡片 ‘%1$s’ 失敗。\n %2$s - - - 問題 - 排序欄位 - - - 答案 - 卡片 - 牌組 - 筆記 - 問題 - 標籤 - 答錯次數 - 複習次數 - 間期 - 難易度 - 到期 - 已修改卡片 - 已建立 - 已修改筆記 - 標籤 修改今日新卡片上限 diff --git a/AnkiDroid/src/main/res/values-zu/02-strings.xml b/AnkiDroid/src/main/res/values-zu/02-strings.xml index f36cc4a2c47e..f7d2d304f631 100644 --- a/AnkiDroid/src/main/res/values-zu/02-strings.xml +++ b/AnkiDroid/src/main/res/values-zu/02-strings.xml @@ -80,27 +80,6 @@ Fatal Error: WebView renderer crashed. Cause: %s System WebView Rendering Failure System WebView failed to render card \'%1$s\'.\n %2$s - - - Question - Sort field - - - Answer - Card - Deck - Note - Question - Tags - Lapses - Reviews - Interval - Ease - Due - Card Modified - Created - Note Modified - Flags Modify today’s new card limit From bebf14fecef69dfc6afb81909eaaf6dea133664d Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Wed, 19 Jun 2024 14:47:51 +0100 Subject: [PATCH 102/138] chore: ignore Kotlin 2 .salive files This appears to be a 'session-is-alive' file https://github.com/JetBrains/kotlin/blob/ca34e5d2fd255ed0501bae4fae3d3691dc40d375/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt#L458 Example: .kotlin/sessions/kotlin-compiler-9293527262404664068.salive --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 37af54b22dec..d77b9ebfbe1f 100644 --- a/.gitignore +++ b/.gitignore @@ -63,3 +63,7 @@ AnkiDroid/ACRA-INSTALLATION #ignore the local insufficient memory for the Java Runtime Environment files hs_err_pid* + +# Ignore kotlin 2.0 compiler files (.salive: session-is-alive) +# https://github.com/JetBrains/kotlin/blob/ca34e5d2fd255ed0501bae4fae3d3691dc40d375/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt#L458 +/.kotlin From 5a13cfba501afc51861accf1e9eab128c8b85cf2 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Wed, 19 Jun 2024 17:00:57 +0000 Subject: [PATCH 103/138] Bumped version to 2.19alpha5 --- AnkiDroid/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AnkiDroid/build.gradle b/AnkiDroid/build.gradle index 5487f9db74ad..b610cf3d3aa9 100644 --- a/AnkiDroid/build.gradle +++ b/AnkiDroid/build.gradle @@ -74,8 +74,8 @@ android { // // This ensures the correct ordering between the various types of releases (dev < alpha < beta < release) which is // needed for upgrades to be offered correctly. - versionCode=21900104 - versionName="2.19alpha4" + versionCode=21900105 + versionName="2.19alpha5" minSdk libs.versions.minSdk.get().toInteger() // After #13695: change .tests_emulator.yml targetSdk libs.versions.targetSdk.get().toInteger() From f6653ea0ac7d169b3f8f7f4183ea36e8a665ab59 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:42:11 +0100 Subject: [PATCH 104/138] chore: `Float.clamp` util --- .../com/ichi2/anki/common/utils/ext/Float.kt | 27 ++++++++++ .../ichi2/anki/common/utils/ext/FloatTest.kt | 50 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 common/src/main/java/com/ichi2/anki/common/utils/ext/Float.kt create mode 100644 common/src/test/java/com/ichi2/anki/common/utils/ext/FloatTest.kt diff --git a/common/src/main/java/com/ichi2/anki/common/utils/ext/Float.kt b/common/src/main/java/com/ichi2/anki/common/utils/ext/Float.kt new file mode 100644 index 000000000000..2ea2d5fb32fd --- /dev/null +++ b/common/src/main/java/com/ichi2/anki/common/utils/ext/Float.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 David Allison + * + * 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 . + */ + +package com.ichi2.anki.common.utils.ext + +/** + * Ensures the number is within the provided range. + * + * If too small, [min] is returned + * If too large, [max] is returned + * + * This does NOT validate that min < max for performance reasons + */ +fun Float.clamp(min: Float, max: Float) = this.coerceIn(minimumValue = min, maximumValue = max) diff --git a/common/src/test/java/com/ichi2/anki/common/utils/ext/FloatTest.kt b/common/src/test/java/com/ichi2/anki/common/utils/ext/FloatTest.kt new file mode 100644 index 000000000000..71d7abacd98d --- /dev/null +++ b/common/src/test/java/com/ichi2/anki/common/utils/ext/FloatTest.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 David Allison + * + * 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 . + */ + +package com.ichi2.anki.common.utils.ext + +import androidx.core.math.MathUtils.clamp +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.Test + +/** + * Tests for methods in [Float][clamp] + */ +class FloatTest { + + @Test + fun clampOneZero() { + fun Float.clampOneZero() = this.clamp(0f, 1f) + + assertThat(1.0f.clampOneZero(), equalTo(1.0f)) + assertThat(1.1f.clampOneZero(), equalTo(1.0f)) + + assertThat(0.0f.clampOneZero(), equalTo(0.0f)) + assertThat((-1.0f).clampOneZero(), equalTo(0.0f)) + + assertThat((0.5f).clampOneZero(), equalTo(0.5f)) + assertThat((0.3f).clampOneZero(), equalTo(0.3f)) + } + + @Test + fun clampCustomValue() { + fun Float.clampPercentage() = this.clamp(0f, 1000f) + + assertThat(1.0f.clampPercentage(), equalTo(1.0f)) + assertThat(1.1f.clampPercentage(), equalTo(1.1f)) + } +} From 3d33211823b402d890b0a29c8454bb55c4ec1ee8 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:55:38 +0100 Subject: [PATCH 105/138] chore: `darkenColor` util --- .../ichi2/anki/utils/android/ColorUtils.kt | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 common/src/main/java/com/ichi2/anki/utils/android/ColorUtils.kt diff --git a/common/src/main/java/com/ichi2/anki/utils/android/ColorUtils.kt b/common/src/main/java/com/ichi2/anki/utils/android/ColorUtils.kt new file mode 100644 index 000000000000..1583766a2b68 --- /dev/null +++ b/common/src/main/java/com/ichi2/anki/utils/android/ColorUtils.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 David Allison + * + * 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 . + */ + +package com.ichi2.anki.utils.android + +import android.graphics.Color +import androidx.annotation.ColorInt +import com.ichi2.anki.common.utils.ext.clamp + +/** + * Darkens the provided ARGB color by a provided [factor] + * + * @param argb The ARGB color to transform + * @param factor Amount to darken, between 1.0f (no change) and 0.0f (black) + * @return The darkened color in ARGB + */ +@ColorInt +fun darkenColor(@ColorInt argb: Int, factor: Float): Int { + val hsv = argb.toHSV() + // https://en.wikipedia.org/wiki/HSL_and_HSV + // The third component is the 'value', or 'lightness/darkness' + hsv[2] = (hsv[2] * factor).clamp(0f, 1f) + return Color.HSVToColor(hsv) +} + +/** + * Converts an ARGB color to an array of its HSV components + * + * [0] is Hue: `[0..360[` + * [1] is Saturation: `[0...1]` + * [2] is Value: `[0...1]` + */ +private fun Int.toHSV(): FloatArray = FloatArray(3).also { arr -> + Color.colorToHSV(this, arr) +} From 6c39ce285830f774fbf8ba422e06bfac81c920e9 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:58:54 +0100 Subject: [PATCH 106/138] docs: Flag.setUserFlag --- AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt b/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt index b45af7a8697d..83fef3b6b90f 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt @@ -24,6 +24,7 @@ import com.ichi2.libanki.Card import com.ichi2.libanki.CardId import com.ichi2.libanki.Collection import org.json.JSONObject +import timber.log.Timber enum class Flag(val code: Int, @DrawableRes val drawableRes: Int, @ColorRes val browserColorRes: Int?) { NONE(0, R.drawable.ic_flag_transparent, null), @@ -108,5 +109,8 @@ private value class FlagLabels(val value: JSONObject) { } } -fun Collection.setUserFlag(flag: Flag, cids: List) = this.setUserFlag(flag.code, cids) +fun Collection.setUserFlag(flag: Flag, cids: List) { + Timber.d("Flagging %d card(s) as %s", cids.size, flag) + this.setUserFlag(flag.code, cids) +} fun Card.setUserFlag(flag: Flag) = this.setUserFlag(flag.code) From dac0c2d6f1ddb0c5de2a9c0094111f8d0c443f37 Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:59:37 +0100 Subject: [PATCH 107/138] docs: removeNotes --- AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt index ff1ca120d29f..a68893a6de2d 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt @@ -569,7 +569,9 @@ class Collection( } fun removeNotes(nids: Iterable = listOf(), cids: Iterable = listOf()): OpChangesWithCount { - return backend.removeNotes(noteIds = nids, cardIds = cids) + return backend.removeNotes(noteIds = nids, cardIds = cids).also { + Timber.d("removeNotes: %d changes", it.count) + } } fun removeCardsAndOrphanedNotes(cardIds: Iterable) { From bf5b6d17468dbcfb7c0913814c74457e2ed601df Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Wed, 19 Jun 2024 16:00:20 +0100 Subject: [PATCH 108/138] refactor: 'browser'-related APIs All non-functional, in preparation for moving to the backend for rendering --- .../src/main/java/com/ichi2/anki/AnkiDroidJsAPI.kt | 10 +++++----- .../ichi2/anki/browser/BrowserColumnCollection.kt | 14 ++++++++++---- .../com/ichi2/anki/browser/CardBrowserViewModel.kt | 1 + 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidJsAPI.kt b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidJsAPI.kt index bef0f541589f..709593ed4a7b 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidJsAPI.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidJsAPI.kt @@ -398,13 +398,13 @@ open class AnkiDroidJsAPI(private val activity: AbstractFlashcardViewer) { return@withContext convertToByteArray(apiContract, false) } val searchResult: MutableList = ArrayList() - for (s in cards) { + for (card in cards.map { it.card }) { val jsonObject = JSONObject() - val fieldsData = s.card.note(getColUnsafe).fields - val fieldsName = s.card.noteType(getColUnsafe).fieldsNames + val fieldsData = card.note(getColUnsafe).fields + val fieldsName = card.noteType(getColUnsafe).fieldsNames - val noteId = s.card.nid - val cardId = s.card.id + val noteId = card.nid + val cardId = card.id jsonObject.put("cardId", cardId) jsonObject.put("noteId", noteId) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt index 6a64b2af9446..a58b0076ac72 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt @@ -63,21 +63,27 @@ class BrowserColumnCollection(val columns: List) { } /** - * @param block Update the column list here. `null` meaning 'none' + * @param block Update the column list here. `null` meaning 'none'. + * Return `false` if no changes should be made + * + * @return the updated [BrowserColumnCollection], or `null` if [block] returned `false` so + * no changes were made */ fun update( prefs: SharedPreferences, mode: CardsOrNotes, block: (MutableList) -> Boolean - ) { + ): BrowserColumnCollection? { val valuesToUpdate: MutableList = load(prefs, mode).columns.toMutableList() if (!block(valuesToUpdate)) { Timber.d("no changes requested") - return + return null } // as in AnkiMobile, this converts: [QUESTION, NONE, TAGS] into [QUESTION, TAGS] val updatedValues = valuesToUpdate.filterNotNull() - save(prefs, mode, BrowserColumnCollection(updatedValues)) + return BrowserColumnCollection(updatedValues).also { + save(prefs, mode, it) + } } fun save(prefs: SharedPreferences, mode: CardsOrNotes, value: BrowserColumnCollection) { diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index 61d683e0f39a..7adc5da32a32 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -457,6 +457,7 @@ class CardBrowserViewModel( /** emits a new value in [flowOfSelectedRows] */ private fun refreshSelectedRowsFlow() = viewModelScope.launch { refreshSelectedRowsFlow.emit(Unit) + Timber.d("refreshed selected rows") } fun selectedRowCount(): Int = selectedRows.size From 8a75195321e95ec51db68e375a1fc94bad53a46b Mon Sep 17 00:00:00 2001 From: lukstbit <52494258+lukstbit@users.noreply.github.com> Date: Thu, 20 Jun 2024 10:33:26 +0300 Subject: [PATCH 109/138] Add proguard rules for common module The rules added are the ones used by the :AnkiDroid module. --- common/proguard-rules.pro | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/common/proguard-rules.pro b/common/proguard-rules.pro index 481bb4348141..a8fc6406dc36 100644 --- a/common/proguard-rules.pro +++ b/common/proguard-rules.pro @@ -18,4 +18,18 @@ # If you keep the line number information, uncomment this to # hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file +#-renamesourcefileattribute SourceFile + +# FIXME remove this entire Android 4.2 workaround from 12/3/15 timrae commit for 2.15.x+ +# Samsung Android 4.2 bug workaround +# https://code.google.com/p/android/issues/detail?id=78377 +-keepattributes ** +-keep class !android.support.v7.view.menu.**,!android.support.design.internal.NavigationMenu,!android.support.design.internal.NavigationMenuPresenter,!android.support.design.internal.NavigationSubMenu,** {*;} +#5806 - Class: ActionBarOverflow +-keep public class android.support.v7.internal.view.menu.** { *; } +-keep public class androidx.appcompat.view.menu.** { *; } +-dontpreverify +-dontoptimize +-dontshrink +-dontwarn ** +-dontnote ** \ No newline at end of file From 11f7d5a7c5a0d6c3620aecca6b276b02b612233b Mon Sep 17 00:00:00 2001 From: lukstbit <52494258+lukstbit@users.noreply.github.com> Date: Thu, 20 Jun 2024 10:42:45 +0300 Subject: [PATCH 110/138] Change source/kotlin compatibility in common module to Java 11 --- common/build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 90d195acdfb9..e67fbefa9849 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -27,11 +27,11 @@ android { } } compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "11" } } From bd296276fb60a52a4cc6331757abe94427a1ec6b Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Thu, 20 Jun 2024 13:11:55 +0100 Subject: [PATCH 111/138] improvement(rename-flag): remove 'ok/cancel' * This made it more obvious that the 'tick' should be pressed * Cancel didn't work as expected * OK didn't perform saves Prompted by https://redirect.github.com/ankidroid/Anki-Android/pull/16244#issuecomment-2180497998 Related: 16205 --- .../ichi2/anki/dialogs/FlagRenameDialog.kt | 24 ------------------- AnkiDroid/src/main/res/values/03-dialogs.xml | 3 --- 2 files changed, 27 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagRenameDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagRenameDialog.kt index ab86381101c5..44d9e7987ad1 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagRenameDialog.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/FlagRenameDialog.kt @@ -28,10 +28,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.ichi2.anki.Flag import com.ichi2.anki.R -import com.ichi2.anki.showThemedToast import com.ichi2.utils.customView -import com.ichi2.utils.negativeButton -import com.ichi2.utils.positiveButton import com.ichi2.utils.title import kotlinx.coroutines.launch import timber.log.Timber @@ -48,9 +45,6 @@ class FlagRenameDialog : DialogFragment() { val builder = AlertDialog.Builder(requireContext()).apply { customView(view = dialogView, 4, 4, 4, 4) title(R.string.rename_flag) - // positiveButton is set in onResume so dialog is not always dismissed - positiveButton(R.string.dialog_ok, click = null) - negativeButton(R.string.dialog_cancel) } val dialog = builder.create() @@ -59,24 +53,6 @@ class FlagRenameDialog : DialogFragment() { return dialog } - override fun onResume() { - super.onResume() - (dialog as AlertDialog).positiveButton.setOnClickListener { - // TODO: Extract pending changes from the adapter and save them - if (!::flagAdapter.isInitialized) return@setOnClickListener - val pendingChanges = flagAdapter.currentList.filter { it.isInEditMode } - if (pendingChanges.any()) { - Timber.i("Attempted to close with %d pending changes", pendingChanges.size) - showThemedToast(R.string.confirm_before_saving, true) - return@setOnClickListener - } - - Timber.i("Closing dialog", pendingChanges.size) - activity?.invalidateOptionsMenu() - dismiss() - } - } - override fun onDismiss(dialog: DialogInterface) { super.onDismiss(dialog) activity?.invalidateOptionsMenu() diff --git a/AnkiDroid/src/main/res/values/03-dialogs.xml b/AnkiDroid/src/main/res/values/03-dialogs.xml index 4f5fa9c1343b..dcb26acbb988 100644 --- a/AnkiDroid/src/main/res/values/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values/03-dialogs.xml @@ -278,7 +278,4 @@ also changes the interval of the card" The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - - Confirm all changes before saving From 87b4ec91bb61813347c3f79117057054ce8a5299 Mon Sep 17 00:00:00 2001 From: Voczi Date: Thu, 20 Jun 2024 16:25:06 +0200 Subject: [PATCH 112/138] Exclude robolectric deps from release --- AnkiDroid/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AnkiDroid/build.gradle b/AnkiDroid/build.gradle index b610cf3d3aa9..140173dc21c5 100644 --- a/AnkiDroid/build.gradle +++ b/AnkiDroid/build.gradle @@ -345,7 +345,7 @@ dependencies { testImplementation files("../../Anki-Android-Backend/rsdroid-testing/build/libs/rsdroid-testing.jar") } else { implementation libs.ankiBackend.backend - implementation libs.ankiBackend.testing + testImplementation libs.ankiBackend.testing } // May need a resolution strategy for support libs to our versions From f1732d35c94a718250102518d5477209e4945dbc Mon Sep 17 00:00:00 2001 From: AnkiDroid Translations Date: Thu, 20 Jun 2024 14:01:20 +0000 Subject: [PATCH 113/138] Updated strings from Crowdin --- AnkiDroid/src/main/res/values-af/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-am/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ar/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-az/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-be/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-bg/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-bn/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ca/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ckb/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-cs/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-da/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-de/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-el/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-eo/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-et/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-eu/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-fa/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-fi/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-fil/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-fr/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-fy/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ga/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-gl/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-got/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-gu/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-heb/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-hi/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-hr/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-hu/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-hy/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ind/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-is/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-it/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-iw/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ja/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-jv/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ka/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-kk/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-km/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-kn/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ko/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ku/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ky/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-lt/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-lv/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-mk/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ml/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-mn/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-mr/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ms/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-my/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-nl/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-nn/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-no/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-or/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-pa/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-pl/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ro/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ru/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-sat/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-sc/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-sk/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-sl/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-sq/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-sr/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ss/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-sv/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-sw/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ta/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-te/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-tg/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-tgl/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-th/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ti/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-tn/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-tr/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ts/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-tt/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-uk/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ur/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-uz/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-ve/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-vi/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-wo/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-xh/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-yue/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml | 2 -- AnkiDroid/src/main/res/values-zu/03-dialogs.xml | 2 -- 93 files changed, 186 deletions(-) diff --git a/AnkiDroid/src/main/res/values-af/03-dialogs.xml b/AnkiDroid/src/main/res/values-af/03-dialogs.xml index fc7327f21a86..d5bce816b0e6 100644 --- a/AnkiDroid/src/main/res/values-af/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-af/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-am/03-dialogs.xml b/AnkiDroid/src/main/res/values-am/03-dialogs.xml index d3f9afa52712..2d06df7413c3 100644 --- a/AnkiDroid/src/main/res/values-am/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-am/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ar/03-dialogs.xml b/AnkiDroid/src/main/res/values-ar/03-dialogs.xml index 416ac58c2f4a..0a800c6b71a6 100644 --- a/AnkiDroid/src/main/res/values-ar/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ar/03-dialogs.xml @@ -290,6 +290,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-az/03-dialogs.xml b/AnkiDroid/src/main/res/values-az/03-dialogs.xml index e62e1bb91134..205d8b402cf8 100644 --- a/AnkiDroid/src/main/res/values-az/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-az/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-be/03-dialogs.xml b/AnkiDroid/src/main/res/values-be/03-dialogs.xml index b1c6f5fe3520..9c712987d760 100644 --- a/AnkiDroid/src/main/res/values-be/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-be/03-dialogs.xml @@ -276,6 +276,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-bg/03-dialogs.xml b/AnkiDroid/src/main/res/values-bg/03-dialogs.xml index 6773d03c981f..ed2ca2fde57e 100644 --- a/AnkiDroid/src/main/res/values-bg/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-bg/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-bn/03-dialogs.xml b/AnkiDroid/src/main/res/values-bn/03-dialogs.xml index 9066799d2670..2decffbab229 100644 --- a/AnkiDroid/src/main/res/values-bn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-bn/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ca/03-dialogs.xml b/AnkiDroid/src/main/res/values-ca/03-dialogs.xml index 3bb6368127a2..b4bf13137ec2 100644 --- a/AnkiDroid/src/main/res/values-ca/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ca/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml b/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml index 778ae2931f5c..80664e9ae6c7 100644 --- a/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ckb/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-cs/03-dialogs.xml b/AnkiDroid/src/main/res/values-cs/03-dialogs.xml index c3b0b3d20b50..42d7ba177171 100644 --- a/AnkiDroid/src/main/res/values-cs/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-cs/03-dialogs.xml @@ -274,6 +274,4 @@ Open Systémový WebView je zastaralý. Některé funkce nebudou fungovat správně. Aktualizujte jej prosím.\n\nNainstalovaná verze: %1$d\nMinimální požadovaná verze: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-da/03-dialogs.xml b/AnkiDroid/src/main/res/values-da/03-dialogs.xml index 1936d6405ac9..3180bc04145c 100644 --- a/AnkiDroid/src/main/res/values-da/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-da/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-de/03-dialogs.xml b/AnkiDroid/src/main/res/values-de/03-dialogs.xml index 1d1f830df9cb..04f813689248 100644 --- a/AnkiDroid/src/main/res/values-de/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-de/03-dialogs.xml @@ -256,6 +256,4 @@ Offen Das System-WebView ist veraltet. Einige Funktionen werden nicht korrekt funktionieren. Bitte aktualisieren Sie es.\n\nInstallierte Version: %1$d\nMindestanforderung: %2$d - - Alle Änderungen vor dem Speichern bestätigen diff --git a/AnkiDroid/src/main/res/values-el/03-dialogs.xml b/AnkiDroid/src/main/res/values-el/03-dialogs.xml index 399b21ca757f..0417f5c2b24c 100644 --- a/AnkiDroid/src/main/res/values-el/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-el/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-eo/03-dialogs.xml b/AnkiDroid/src/main/res/values-eo/03-dialogs.xml index 086edebaaf18..cc0419129514 100644 --- a/AnkiDroid/src/main/res/values-eo/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-eo/03-dialogs.xml @@ -258,6 +258,4 @@ Malfermi The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml b/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml index 6e99e3b59144..7127603dd726 100644 --- a/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-es-rAR/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml b/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml index 5887b7e30b52..233e77890d32 100644 --- a/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-es-rES/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-et/03-dialogs.xml b/AnkiDroid/src/main/res/values-et/03-dialogs.xml index 341827ed8b2e..ba25be3e26e8 100644 --- a/AnkiDroid/src/main/res/values-et/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-et/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-eu/03-dialogs.xml b/AnkiDroid/src/main/res/values-eu/03-dialogs.xml index 133490926e26..e48ce0051554 100644 --- a/AnkiDroid/src/main/res/values-eu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-eu/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-fa/03-dialogs.xml b/AnkiDroid/src/main/res/values-fa/03-dialogs.xml index 7d48136850b5..ed55abacb864 100644 --- a/AnkiDroid/src/main/res/values-fa/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fa/03-dialogs.xml @@ -256,6 +256,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-fi/03-dialogs.xml b/AnkiDroid/src/main/res/values-fi/03-dialogs.xml index 85e7c3ca9b0c..c5d91ad7cd37 100644 --- a/AnkiDroid/src/main/res/values-fi/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fi/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-fil/03-dialogs.xml b/AnkiDroid/src/main/res/values-fil/03-dialogs.xml index 35eb92eb5fb4..43db4504ecf0 100644 --- a/AnkiDroid/src/main/res/values-fil/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fil/03-dialogs.xml @@ -259,6 +259,4 @@ Mga file na may di-wastong pag-encode:%d Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-fr/03-dialogs.xml b/AnkiDroid/src/main/res/values-fr/03-dialogs.xml index d9c937dd9ba6..d4aa8c68cfe5 100644 --- a/AnkiDroid/src/main/res/values-fr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fr/03-dialogs.xml @@ -256,6 +256,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-fy/03-dialogs.xml b/AnkiDroid/src/main/res/values-fy/03-dialogs.xml index 085319fbc070..938497444a06 100644 --- a/AnkiDroid/src/main/res/values-fy/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-fy/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ga/03-dialogs.xml b/AnkiDroid/src/main/res/values-ga/03-dialogs.xml index 477a1c94288b..11a0314a4b7b 100644 --- a/AnkiDroid/src/main/res/values-ga/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ga/03-dialogs.xml @@ -282,6 +282,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-gl/03-dialogs.xml b/AnkiDroid/src/main/res/values-gl/03-dialogs.xml index c0ee042cd0ca..4ddaa7e154ac 100644 --- a/AnkiDroid/src/main/res/values-gl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-gl/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-got/03-dialogs.xml b/AnkiDroid/src/main/res/values-got/03-dialogs.xml index 852d5173860a..f51b3a593f66 100644 --- a/AnkiDroid/src/main/res/values-got/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-got/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-gu/03-dialogs.xml b/AnkiDroid/src/main/res/values-gu/03-dialogs.xml index 909fc5817b47..6548f5e0ba9a 100644 --- a/AnkiDroid/src/main/res/values-gu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-gu/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-heb/03-dialogs.xml b/AnkiDroid/src/main/res/values-heb/03-dialogs.xml index 9a86ffa986be..c58e9db8c984 100644 --- a/AnkiDroid/src/main/res/values-heb/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-heb/03-dialogs.xml @@ -273,6 +273,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-hi/03-dialogs.xml b/AnkiDroid/src/main/res/values-hi/03-dialogs.xml index e2a2bb23ab81..8700986266b3 100644 --- a/AnkiDroid/src/main/res/values-hi/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hi/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-hr/03-dialogs.xml b/AnkiDroid/src/main/res/values-hr/03-dialogs.xml index 6826045d7a4a..9472f65feb64 100644 --- a/AnkiDroid/src/main/res/values-hr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hr/03-dialogs.xml @@ -266,6 +266,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-hu/03-dialogs.xml b/AnkiDroid/src/main/res/values-hu/03-dialogs.xml index 561ffb9238af..caf4f1fcf52c 100644 --- a/AnkiDroid/src/main/res/values-hu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hu/03-dialogs.xml @@ -256,6 +256,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-hy/03-dialogs.xml b/AnkiDroid/src/main/res/values-hy/03-dialogs.xml index 9e1427d1ea56..3b5f4ff6369a 100644 --- a/AnkiDroid/src/main/res/values-hy/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-hy/03-dialogs.xml @@ -256,6 +256,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ind/03-dialogs.xml b/AnkiDroid/src/main/res/values-ind/03-dialogs.xml index 7a25a9456999..fb15d6525215 100644 --- a/AnkiDroid/src/main/res/values-ind/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ind/03-dialogs.xml @@ -250,6 +250,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-is/03-dialogs.xml b/AnkiDroid/src/main/res/values-is/03-dialogs.xml index 192f20aa2d24..13b381bf73d2 100644 --- a/AnkiDroid/src/main/res/values-is/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-is/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-it/03-dialogs.xml b/AnkiDroid/src/main/res/values-it/03-dialogs.xml index 68159ad476b3..ffd104fb259b 100644 --- a/AnkiDroid/src/main/res/values-it/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-it/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-iw/03-dialogs.xml b/AnkiDroid/src/main/res/values-iw/03-dialogs.xml index 9a86ffa986be..c58e9db8c984 100644 --- a/AnkiDroid/src/main/res/values-iw/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-iw/03-dialogs.xml @@ -273,6 +273,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml index 5c85a3e3f415..ce66c60f8a6c 100644 --- a/AnkiDroid/src/main/res/values-ja/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ja/03-dialogs.xml @@ -249,6 +249,4 @@ 開く 「AndroidシステムのWebView 」(または「Android System WebView」)が古くなっています。いくつかの機能が正しく動作しません。更新してください。\n\nインストールされているバージョン: %1$d\n最低限必要なバージョン: %2$d - - 編集中のフラグがあります。保存する前に編集を終了してください。 diff --git a/AnkiDroid/src/main/res/values-jv/03-dialogs.xml b/AnkiDroid/src/main/res/values-jv/03-dialogs.xml index 0680d160e7ec..f1f35c733f05 100644 --- a/AnkiDroid/src/main/res/values-jv/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-jv/03-dialogs.xml @@ -250,6 +250,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ka/03-dialogs.xml b/AnkiDroid/src/main/res/values-ka/03-dialogs.xml index 03edf32d5617..44c11864667c 100644 --- a/AnkiDroid/src/main/res/values-ka/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ka/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-kk/03-dialogs.xml b/AnkiDroid/src/main/res/values-kk/03-dialogs.xml index f0e28ffe2bbe..28ab9ec10660 100644 --- a/AnkiDroid/src/main/res/values-kk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-kk/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-km/03-dialogs.xml b/AnkiDroid/src/main/res/values-km/03-dialogs.xml index eed6bb7903c4..110351f03a39 100644 --- a/AnkiDroid/src/main/res/values-km/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-km/03-dialogs.xml @@ -250,6 +250,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-kn/03-dialogs.xml b/AnkiDroid/src/main/res/values-kn/03-dialogs.xml index 6133fd3b10d7..fef2942cbeb0 100644 --- a/AnkiDroid/src/main/res/values-kn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-kn/03-dialogs.xml @@ -256,6 +256,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ko/03-dialogs.xml b/AnkiDroid/src/main/res/values-ko/03-dialogs.xml index a4d4cd6b3c46..c6897836dff6 100644 --- a/AnkiDroid/src/main/res/values-ko/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ko/03-dialogs.xml @@ -250,6 +250,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ku/03-dialogs.xml b/AnkiDroid/src/main/res/values-ku/03-dialogs.xml index 778ae2931f5c..80664e9ae6c7 100644 --- a/AnkiDroid/src/main/res/values-ku/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ku/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ky/03-dialogs.xml b/AnkiDroid/src/main/res/values-ky/03-dialogs.xml index 5dbe01d72fb0..43bdad1b692f 100644 --- a/AnkiDroid/src/main/res/values-ky/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ky/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-lt/03-dialogs.xml b/AnkiDroid/src/main/res/values-lt/03-dialogs.xml index bf3642e560a6..3da29e029914 100644 --- a/AnkiDroid/src/main/res/values-lt/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-lt/03-dialogs.xml @@ -274,6 +274,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-lv/03-dialogs.xml b/AnkiDroid/src/main/res/values-lv/03-dialogs.xml index 7166459b62b9..c6f06f46a2d2 100644 --- a/AnkiDroid/src/main/res/values-lv/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-lv/03-dialogs.xml @@ -266,6 +266,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-mk/03-dialogs.xml b/AnkiDroid/src/main/res/values-mk/03-dialogs.xml index 10b365bc4550..07c201640b45 100644 --- a/AnkiDroid/src/main/res/values-mk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mk/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ml/03-dialogs.xml b/AnkiDroid/src/main/res/values-ml/03-dialogs.xml index 895fdf826fc9..5ae1f2af79b5 100644 --- a/AnkiDroid/src/main/res/values-ml/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ml/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-mn/03-dialogs.xml b/AnkiDroid/src/main/res/values-mn/03-dialogs.xml index f7477e9caaea..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-mn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mn/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-mr/03-dialogs.xml b/AnkiDroid/src/main/res/values-mr/03-dialogs.xml index 20fef009de7a..93e555f566bd 100644 --- a/AnkiDroid/src/main/res/values-mr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-mr/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ms/03-dialogs.xml b/AnkiDroid/src/main/res/values-ms/03-dialogs.xml index 7acf4ace659e..d77fdd6042da 100644 --- a/AnkiDroid/src/main/res/values-ms/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ms/03-dialogs.xml @@ -250,6 +250,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-my/03-dialogs.xml b/AnkiDroid/src/main/res/values-my/03-dialogs.xml index d55f88add175..15b91c530f36 100644 --- a/AnkiDroid/src/main/res/values-my/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-my/03-dialogs.xml @@ -250,6 +250,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-nl/03-dialogs.xml b/AnkiDroid/src/main/res/values-nl/03-dialogs.xml index 9f969b794547..e5aa19200793 100644 --- a/AnkiDroid/src/main/res/values-nl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-nl/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-nn/03-dialogs.xml b/AnkiDroid/src/main/res/values-nn/03-dialogs.xml index fb291abc7cc6..fdf1e3021453 100644 --- a/AnkiDroid/src/main/res/values-nn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-nn/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-no/03-dialogs.xml b/AnkiDroid/src/main/res/values-no/03-dialogs.xml index 2a85d3363251..d4070917c157 100644 --- a/AnkiDroid/src/main/res/values-no/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-no/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-or/03-dialogs.xml b/AnkiDroid/src/main/res/values-or/03-dialogs.xml index e9ec65b1096a..e36a3156a075 100644 --- a/AnkiDroid/src/main/res/values-or/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-or/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-pa/03-dialogs.xml b/AnkiDroid/src/main/res/values-pa/03-dialogs.xml index 1893e8a40430..4843cb22d221 100644 --- a/AnkiDroid/src/main/res/values-pa/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pa/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-pl/03-dialogs.xml b/AnkiDroid/src/main/res/values-pl/03-dialogs.xml index 7fc6fbfcb41d..fe8da3065b8e 100644 --- a/AnkiDroid/src/main/res/values-pl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pl/03-dialogs.xml @@ -274,6 +274,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml b/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml index fb959a2ca461..a9f22a956ea4 100644 --- a/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pt-rBR/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml b/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml index 336394714f74..9a4bc5c39ac6 100644 --- a/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-pt-rPT/03-dialogs.xml @@ -258,6 +258,4 @@ Abrir O sistema WebView está desatualizado. Alguns recursos não funcionarão corretamente. Atualize-o.\n\nVersão instalada: %1$d\nVersão mínima necessária: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ro/03-dialogs.xml b/AnkiDroid/src/main/res/values-ro/03-dialogs.xml index 54494a7151d9..1012cb1082ea 100644 --- a/AnkiDroid/src/main/res/values-ro/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ro/03-dialogs.xml @@ -266,6 +266,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ru/03-dialogs.xml b/AnkiDroid/src/main/res/values-ru/03-dialogs.xml index e1063a01bb72..6f321ba1ccae 100644 --- a/AnkiDroid/src/main/res/values-ru/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ru/03-dialogs.xml @@ -275,6 +275,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sat/03-dialogs.xml b/AnkiDroid/src/main/res/values-sat/03-dialogs.xml index b7246cc045a5..c835d8064214 100644 --- a/AnkiDroid/src/main/res/values-sat/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sat/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sc/03-dialogs.xml b/AnkiDroid/src/main/res/values-sc/03-dialogs.xml index 1858dba65581..2134871aa271 100644 --- a/AnkiDroid/src/main/res/values-sc/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sc/03-dialogs.xml @@ -272,6 +272,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sk/03-dialogs.xml b/AnkiDroid/src/main/res/values-sk/03-dialogs.xml index e126314891d8..bff167a01072 100644 --- a/AnkiDroid/src/main/res/values-sk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sk/03-dialogs.xml @@ -272,6 +272,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sl/03-dialogs.xml b/AnkiDroid/src/main/res/values-sl/03-dialogs.xml index 2331e0b1c284..2cf9c93e032a 100644 --- a/AnkiDroid/src/main/res/values-sl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sl/03-dialogs.xml @@ -274,6 +274,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sq/03-dialogs.xml b/AnkiDroid/src/main/res/values-sq/03-dialogs.xml index 05adce91d63b..46782b2ea83a 100644 --- a/AnkiDroid/src/main/res/values-sq/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sq/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sr/03-dialogs.xml b/AnkiDroid/src/main/res/values-sr/03-dialogs.xml index d3814f60101a..9917e1e6ce91 100644 --- a/AnkiDroid/src/main/res/values-sr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sr/03-dialogs.xml @@ -266,6 +266,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ss/03-dialogs.xml b/AnkiDroid/src/main/res/values-ss/03-dialogs.xml index f7477e9caaea..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-ss/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ss/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sv/03-dialogs.xml b/AnkiDroid/src/main/res/values-sv/03-dialogs.xml index 08644981023c..0c576931e50e 100644 --- a/AnkiDroid/src/main/res/values-sv/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sv/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-sw/03-dialogs.xml b/AnkiDroid/src/main/res/values-sw/03-dialogs.xml index f7477e9caaea..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-sw/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-sw/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ta/03-dialogs.xml b/AnkiDroid/src/main/res/values-ta/03-dialogs.xml index a72bc28a8f82..bda43a1ce1d4 100644 --- a/AnkiDroid/src/main/res/values-ta/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ta/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-te/03-dialogs.xml b/AnkiDroid/src/main/res/values-te/03-dialogs.xml index 319d3eb8c707..a0dbe1bfd02c 100644 --- a/AnkiDroid/src/main/res/values-te/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-te/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-tg/03-dialogs.xml b/AnkiDroid/src/main/res/values-tg/03-dialogs.xml index 2a40920bc765..2b091d79c9e2 100644 --- a/AnkiDroid/src/main/res/values-tg/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tg/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml b/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml index 9c0f2592ef01..72a0b3cf8769 100644 --- a/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tgl/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-th/03-dialogs.xml b/AnkiDroid/src/main/res/values-th/03-dialogs.xml index 0680d160e7ec..f1f35c733f05 100644 --- a/AnkiDroid/src/main/res/values-th/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-th/03-dialogs.xml @@ -250,6 +250,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ti/03-dialogs.xml b/AnkiDroid/src/main/res/values-ti/03-dialogs.xml index f7477e9caaea..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-ti/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ti/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-tn/03-dialogs.xml b/AnkiDroid/src/main/res/values-tn/03-dialogs.xml index f7477e9caaea..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-tn/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tn/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-tr/03-dialogs.xml b/AnkiDroid/src/main/res/values-tr/03-dialogs.xml index 26f4b3e99bb1..ffb89753b71c 100644 --- a/AnkiDroid/src/main/res/values-tr/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tr/03-dialogs.xml @@ -258,6 +258,4 @@ Sistem WebView\'su güncel değil. Bazı özellikler doğru çalışmayacak. Lütfen güncelleyin.\n\nYüklü sürüm: %1$d\nGereken en düşük sürüm: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ts/03-dialogs.xml b/AnkiDroid/src/main/res/values-ts/03-dialogs.xml index f7477e9caaea..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-ts/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ts/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-tt/03-dialogs.xml b/AnkiDroid/src/main/res/values-tt/03-dialogs.xml index 4cfacc8ee4a4..eb3823171c0b 100644 --- a/AnkiDroid/src/main/res/values-tt/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-tt/03-dialogs.xml @@ -250,6 +250,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-uk/03-dialogs.xml b/AnkiDroid/src/main/res/values-uk/03-dialogs.xml index b7ed3f24a6d3..9b88fab45539 100644 --- a/AnkiDroid/src/main/res/values-uk/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-uk/03-dialogs.xml @@ -274,6 +274,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ur/03-dialogs.xml b/AnkiDroid/src/main/res/values-ur/03-dialogs.xml index 3a42063f91d9..48f4b6af0e5e 100644 --- a/AnkiDroid/src/main/res/values-ur/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ur/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-uz/03-dialogs.xml b/AnkiDroid/src/main/res/values-uz/03-dialogs.xml index 0b5eaf531c33..73ff762ae652 100644 --- a/AnkiDroid/src/main/res/values-uz/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-uz/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-ve/03-dialogs.xml b/AnkiDroid/src/main/res/values-ve/03-dialogs.xml index f7477e9caaea..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-ve/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-ve/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-vi/03-dialogs.xml b/AnkiDroid/src/main/res/values-vi/03-dialogs.xml index 8bb1f2d8c29a..0414affcf26f 100644 --- a/AnkiDroid/src/main/res/values-vi/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-vi/03-dialogs.xml @@ -250,6 +250,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-wo/03-dialogs.xml b/AnkiDroid/src/main/res/values-wo/03-dialogs.xml index 0680d160e7ec..f1f35c733f05 100644 --- a/AnkiDroid/src/main/res/values-wo/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-wo/03-dialogs.xml @@ -250,6 +250,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-xh/03-dialogs.xml b/AnkiDroid/src/main/res/values-xh/03-dialogs.xml index f7477e9caaea..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-xh/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-xh/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-yue/03-dialogs.xml b/AnkiDroid/src/main/res/values-yue/03-dialogs.xml index 5c58754d77b8..c0d122875325 100644 --- a/AnkiDroid/src/main/res/values-yue/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-yue/03-dialogs.xml @@ -250,6 +250,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml index 659d5babc98c..a1042c33b8bd 100644 --- a/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zh-rCN/03-dialogs.xml @@ -250,6 +250,4 @@ 打开 系统 WebView 已过时。有些功能将无法正常工作。请更新它。\n\n已安装版本: %1$d\n所需最低版本: %2$d - - 保存前确认所有更改 diff --git a/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml b/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml index 29a0a44ef551..3541677286a3 100644 --- a/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zh-rTW/03-dialogs.xml @@ -250,6 +250,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving diff --git a/AnkiDroid/src/main/res/values-zu/03-dialogs.xml b/AnkiDroid/src/main/res/values-zu/03-dialogs.xml index f7477e9caaea..f2470c6ce0a9 100644 --- a/AnkiDroid/src/main/res/values-zu/03-dialogs.xml +++ b/AnkiDroid/src/main/res/values-zu/03-dialogs.xml @@ -258,6 +258,4 @@ Open The system WebView is outdated. Some features won’t work correctly. Please update it.\n\nInstalled version: %1$d\nMinimum required version: %2$d - - Confirm all changes before saving From d2ddaaf122f6d03501bfec0adb88f510d93499f0 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Thu, 20 Jun 2024 15:38:31 +0000 Subject: [PATCH 114/138] Bumped version to 2.19alpha6 --- AnkiDroid/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AnkiDroid/build.gradle b/AnkiDroid/build.gradle index 140173dc21c5..9c18e4117fa2 100644 --- a/AnkiDroid/build.gradle +++ b/AnkiDroid/build.gradle @@ -74,8 +74,8 @@ android { // // This ensures the correct ordering between the various types of releases (dev < alpha < beta < release) which is // needed for upgrades to be offered correctly. - versionCode=21900105 - versionName="2.19alpha5" + versionCode=21900106 + versionName="2.19alpha6" minSdk libs.versions.minSdk.get().toInteger() // After #13695: change .tests_emulator.yml targetSdk libs.versions.targetSdk.get().toInteger() From 4aec82486bf9a89e9209f9735a2ae412aad1e058 Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com> Date: Sat, 27 Apr 2024 09:44:37 -0300 Subject: [PATCH 115/138] feat(new reviewer): card info --- .../anki/ui/windows/reviewer/ReviewerFragment.kt | 15 ++++++++++++--- .../anki/ui/windows/reviewer/ReviewerViewModel.kt | 5 +++++ .../src/main/res/drawable/ic_dialog_info.xml | 2 +- AnkiDroid/src/main/res/menu/reviewer2.xml | 5 +++++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt index 849f4001ad61..373eba6202df 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt @@ -37,11 +37,11 @@ import com.ichi2.anki.previewer.CardViewerActivity import com.ichi2.anki.previewer.CardViewerFragment import com.ichi2.anki.snackbar.BaseSnackbarBuilderProvider import com.ichi2.anki.snackbar.SnackbarBuilder -import com.ichi2.anki.snackbar.showSnackbar import com.ichi2.anki.utils.ext.collectIn import com.ichi2.anki.utils.ext.collectLatestIn import com.ichi2.anki.utils.navBarNeedsScrim import com.ichi2.utils.increaseHorizontalPaddingOfOverflowMenuIcons +import kotlinx.coroutines.launch class ReviewerFragment : CardViewerFragment(R.layout.reviewer2), @@ -97,8 +97,10 @@ class ReviewerFragment : } // TODO - override fun onMenuItemClick(item: MenuItem?): Boolean { - showSnackbar("Not implemented yet") + override fun onMenuItemClick(item: MenuItem): Boolean { + when (item.itemId) { + R.id.action_card_info -> launchCardInfo() + } return true } @@ -135,6 +137,13 @@ class ReviewerFragment : } } + private fun launchCardInfo() { + lifecycleScope.launch { + val intent = viewModel.getCardInfoDestination().toIntent(requireContext()) + startActivity(intent) + } + } + companion object { fun getIntent(context: Context): Intent { return CardViewerActivity.getIntent(context, ReviewerFragment::class) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt index 54bea21586f2..1b4aaac9fe75 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt @@ -25,6 +25,7 @@ import com.ichi2.anki.asyncIO import com.ichi2.anki.cardviewer.CardMediaPlayer import com.ichi2.anki.launchCatchingIO import com.ichi2.anki.pages.AnkiServer +import com.ichi2.anki.pages.CardInfoDestination import com.ichi2.anki.previewer.CardViewerViewModel import com.ichi2.anki.reviewer.CardSide import com.ichi2.libanki.sched.CurrentQueueState @@ -101,6 +102,10 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( statesMutated = true } + suspend fun getCardInfoDestination(): CardInfoDestination { + return CardInfoDestination(currentCard.await().id) + } + /* ********************************************************************************************* *************************************** Internal methods *************************************** ********************************************************************************************* */ diff --git a/AnkiDroid/src/main/res/drawable/ic_dialog_info.xml b/AnkiDroid/src/main/res/drawable/ic_dialog_info.xml index 654cfb396b99..226806703e20 100644 --- a/AnkiDroid/src/main/res/drawable/ic_dialog_info.xml +++ b/AnkiDroid/src/main/res/drawable/ic_dialog_info.xml @@ -1,4 +1,4 @@ - diff --git a/AnkiDroid/src/main/res/menu/reviewer2.xml b/AnkiDroid/src/main/res/menu/reviewer2.xml index ea7c0d8099cb..19e0243ea4b9 100644 --- a/AnkiDroid/src/main/res/menu/reviewer2.xml +++ b/AnkiDroid/src/main/res/menu/reviewer2.xml @@ -26,4 +26,9 @@ android:icon="@drawable/ic_mode_edit_white" android:title="@string/cardeditor_title_edit_card" app:showAsAction="collapseActionView"/> + \ No newline at end of file From ff060ecd658ad1ddd4d3aaf25dce24221a6f998a Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com> Date: Mon, 27 May 2024 06:34:48 -0300 Subject: [PATCH 116/138] feat(new reviewer): deck options --- .../anki/ui/windows/reviewer/ReviewerFragment.kt | 13 +++++++++++++ .../anki/ui/windows/reviewer/ReviewerViewModel.kt | 13 +++++++++++++ AnkiDroid/src/main/res/menu/reviewer2.xml | 5 +++++ 3 files changed, 31 insertions(+) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt index 373eba6202df..c9146e377f75 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt @@ -21,6 +21,7 @@ import android.os.Bundle import android.view.MenuItem import android.view.View import android.webkit.WebView +import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.view.menu.MenuBuilder import androidx.appcompat.widget.ThemeUtils import androidx.appcompat.widget.Toolbar @@ -100,6 +101,7 @@ class ReviewerFragment : override fun onMenuItemClick(item: MenuItem): Boolean { when (item.itemId) { R.id.action_card_info -> launchCardInfo() + R.id.action_open_deck_options -> launchDeckOptions() } return true } @@ -144,6 +146,17 @@ class ReviewerFragment : } } + private val deckOptionsLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + viewModel.handleDeckOptionsResult() + } + + private fun launchDeckOptions() { + lifecycleScope.launch { + val intent = viewModel.getDeckOptionsDestination().getIntent(requireContext()) + deckOptionsLauncher.launch(intent) + } + } + companion object { fun getIntent(context: Context): Intent { return CardViewerActivity.getIntent(context, ReviewerFragment::class) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt index 1b4aaac9fe75..8c928db49452 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt @@ -26,6 +26,7 @@ import com.ichi2.anki.cardviewer.CardMediaPlayer import com.ichi2.anki.launchCatchingIO 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.reviewer.CardSide import com.ichi2.libanki.sched.CurrentQueueState @@ -106,6 +107,18 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( return CardInfoDestination(currentCard.await().id) } + suspend fun getDeckOptionsDestination(): DeckOptionsDestination { + val deckId = withCol { decks.getCurrentId() } + val isFiltered = withCol { decks.isFiltered(deckId) } + return DeckOptionsDestination(deckId, isFiltered) + } + + fun handleDeckOptionsResult() { + launchCatchingIO { + updateCurrentCard() + } + } + /* ********************************************************************************************* *************************************** Internal methods *************************************** ********************************************************************************************* */ diff --git a/AnkiDroid/src/main/res/menu/reviewer2.xml b/AnkiDroid/src/main/res/menu/reviewer2.xml index 19e0243ea4b9..05f5a7b4a0c6 100644 --- a/AnkiDroid/src/main/res/menu/reviewer2.xml +++ b/AnkiDroid/src/main/res/menu/reviewer2.xml @@ -31,4 +31,9 @@ android:icon="@drawable/ic_dialog_info" android:title="@string/card_info_title" app:showAsAction="collapseActionView"/> + \ No newline at end of file From 83d54fc8f836168941a2ecc1a361797eb66a4262 Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com> Date: Mon, 27 May 2024 06:41:54 -0300 Subject: [PATCH 117/138] feat(new reviewer): add and edit note --- .../ui/windows/reviewer/ReviewerFragment.kt | 22 +++++++++++++++++++ .../ui/windows/reviewer/ReviewerViewModel.kt | 17 ++++++++++++++ AnkiDroid/src/main/res/menu/reviewer2.xml | 5 +++++ 3 files changed, 44 insertions(+) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt index c9146e377f75..8f1201df2c51 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt @@ -32,6 +32,7 @@ import androidx.lifecycle.lifecycleScope import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.button.MaterialButton import com.ichi2.anki.AbstractFlashcardViewer.Companion.RESULT_NO_MORE_CARDS +import com.ichi2.anki.NoteEditor import com.ichi2.anki.R import com.ichi2.anki.cardviewer.CardMediaPlayer import com.ichi2.anki.previewer.CardViewerActivity @@ -100,7 +101,9 @@ class ReviewerFragment : // TODO override fun onMenuItemClick(item: MenuItem): Boolean { when (item.itemId) { + R.id.action_add_note -> launchAddNote() R.id.action_card_info -> launchCardInfo() + R.id.action_edit -> launchEditNote() R.id.action_open_deck_options -> launchDeckOptions() } return true @@ -139,6 +142,25 @@ class ReviewerFragment : } } + private val noteEditorLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + viewModel.handleNoteEditorResult(result) + } + + private fun launchEditNote() { + lifecycleScope.launch { + val intent = viewModel.getEditNoteDestination().toIntent(requireContext()) + noteEditorLauncher.launch(intent) + } + } + + private fun launchAddNote() { + val intent = Intent(context, NoteEditor::class.java).apply { + putExtra(NoteEditor.EXTRA_CALLER, NoteEditor.CALLER_REVIEWER_ADD) + } + noteEditorLauncher.launch(intent) + } + private fun launchCardInfo() { lifecycleScope.launch { val intent = viewModel.getCardInfoDestination().toIntent(requireContext()) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt index 8c928db49452..cc99f0652be6 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt @@ -15,12 +15,14 @@ */ package com.ichi2.anki.ui.windows.reviewer +import androidx.activity.result.ActivityResult import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewmodel.initializer import androidx.lifecycle.viewmodel.viewModelFactory import anki.frontend.SetSchedulingStatesRequest import com.ichi2.anki.CollectionManager.withCol import com.ichi2.anki.Ease +import com.ichi2.anki.NoteEditor import com.ichi2.anki.asyncIO import com.ichi2.anki.cardviewer.CardMediaPlayer import com.ichi2.anki.launchCatchingIO @@ -28,6 +30,7 @@ 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.libanki.sched.CurrentQueueState import com.ichi2.libanki.undoableOp @@ -103,6 +106,20 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( statesMutated = true } + suspend fun getEditNoteDestination(): NoteEditorDestination { + return NoteEditorDestination(currentCard.await().id) + } + + fun handleNoteEditorResult(result: ActivityResult) { + if (result.data?.getBooleanExtra(NoteEditor.RELOAD_REQUIRED_EXTRA_KEY, false) == true || + result.data?.getBooleanExtra(NoteEditor.NOTE_CHANGED_EXTRA_KEY, false) == true + ) { + launchCatchingIO { + updateCurrentCard() + } + } + } + suspend fun getCardInfoDestination(): CardInfoDestination { return CardInfoDestination(currentCard.await().id) } diff --git a/AnkiDroid/src/main/res/menu/reviewer2.xml b/AnkiDroid/src/main/res/menu/reviewer2.xml index 05f5a7b4a0c6..46b1bc3dab74 100644 --- a/AnkiDroid/src/main/res/menu/reviewer2.xml +++ b/AnkiDroid/src/main/res/menu/reviewer2.xml @@ -36,4 +36,9 @@ android:icon="@drawable/ic_tune_white" android:title="@string/menu__deck_options" app:showAsAction="never"/> + \ No newline at end of file From 69a3c38b4803522e2da2aff2d7ec919ba3e460c0 Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com> Date: Mon, 27 May 2024 07:00:40 -0300 Subject: [PATCH 118/138] feat(new reviewer): mark --- .../ui/windows/reviewer/ReviewerFragment.kt | 19 ++++++++++++++++ .../ui/windows/reviewer/ReviewerViewModel.kt | 22 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt index 8f1201df2c51..dcb0ef120d60 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt @@ -18,6 +18,7 @@ package com.ichi2.anki.ui.windows.reviewer import android.content.Context import android.content.Intent import android.os.Bundle +import android.view.Menu import android.view.MenuItem import android.view.View import android.webkit.WebView @@ -28,6 +29,7 @@ import androidx.appcompat.widget.Toolbar import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isVisible import androidx.fragment.app.viewModels +import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.button.MaterialButton @@ -70,6 +72,7 @@ class ReviewerFragment : setOnMenuItemClickListener(this@ReviewerFragment) setNavigationOnClickListener { requireActivity().onBackPressedDispatcher.onBackPressed() } (menu as? MenuBuilder)?.let { + setupMenuItems(it) it.setOptionalIconsVisible(true) requireContext().increaseHorizontalPaddingOfOverflowMenuIcons(it) } @@ -104,6 +107,7 @@ class ReviewerFragment : R.id.action_add_note -> launchAddNote() R.id.action_card_info -> launchCardInfo() R.id.action_edit -> launchEditNote() + R.id.action_mark -> viewModel.toggleMark() R.id.action_open_deck_options -> launchDeckOptions() } return true @@ -142,6 +146,21 @@ class ReviewerFragment : } } + private fun setupMenuItems(menu: Menu) { + // TODO show that the card is marked somehow when the menu item is overflowed or not shown + val markItem = menu.findItem(R.id.action_mark) + viewModel.isMarkedFlow.flowWithLifecycle(lifecycle) + .collectLatestIn(lifecycleScope) { isMarked -> + if (isMarked) { + markItem.setIcon(R.drawable.ic_star) + markItem.setTitle(R.string.menu_unmark_note) + } else { + markItem.setIcon(R.drawable.ic_star_border_white) + markItem.setTitle(R.string.menu_mark_note) + } + } + } + private val noteEditorLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> viewModel.handleNoteEditorResult(result) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt index cc99f0652be6..560be447fdbb 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt @@ -32,6 +32,10 @@ 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 +import com.ichi2.libanki.hasTag +import com.ichi2.libanki.note import com.ichi2.libanki.sched.CurrentQueueState import com.ichi2.libanki.undoableOp import com.ichi2.libanki.utils.TimeManager @@ -39,6 +43,7 @@ import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Deferred import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel(cardMediaPlayer) { @@ -50,6 +55,7 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( queueState.await()!!.topCard } var isQueueFinishedFlow = MutableSharedFlow() + val isMarkedFlow = MutableStateFlow(false) override val server = AnkiServer(this).also { it.start() } private val stateMutationKey = TimeManager.time.intTimeMS().toString() @@ -102,6 +108,15 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( fun answerGood() = answerCard(Ease.GOOD) fun answerEasy() = answerCard(Ease.EASY) + fun toggleMark() { + launchCatchingIO { + val card = currentCard.await() + val note = withCol { card.note() } + NoteService.toggleMark(note) + isMarkedFlow.emit(NoteService.isMarked(note)) + } + } + fun onStateMutationCallback() { statesMutated = true } @@ -206,6 +221,12 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( cardMediaPlayer.playAllSoundsForSide(side) } + private suspend fun updateMarkedStatus() { + val card = currentCard.await() + val isMarkedValue = withCol { card.note().hasTag(MARKED_TAG) } + isMarkedFlow.emit(isMarkedValue) + } + private suspend fun updateCurrentCard() { queueState = asyncIO { withCol { @@ -216,6 +237,7 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( currentCard = CompletableDeferred(it.topCard) showQuestion() loadAndPlaySounds(CardSide.QUESTION) + updateMarkedStatus() } ?: isQueueFinishedFlow.emit(true) } From 89c463121fe3b23e3eae42657ae5b18b3872a20c Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com> Date: Mon, 27 May 2024 12:39:56 -0300 Subject: [PATCH 119/138] feat(new reviewer): delete note --- .../anki/ui/windows/reviewer/ReviewerFragment.kt | 7 +++++++ .../anki/ui/windows/reviewer/ReviewerViewModel.kt | 13 +++++++++++++ AnkiDroid/src/main/res/menu/reviewer2.xml | 5 +++++ 3 files changed, 25 insertions(+) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt index dcb0ef120d60..7c263f1c3804 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt @@ -41,6 +41,7 @@ import com.ichi2.anki.previewer.CardViewerActivity import com.ichi2.anki.previewer.CardViewerFragment import com.ichi2.anki.snackbar.BaseSnackbarBuilderProvider import com.ichi2.anki.snackbar.SnackbarBuilder +import com.ichi2.anki.snackbar.showSnackbar import com.ichi2.anki.utils.ext.collectIn import com.ichi2.anki.utils.ext.collectLatestIn import com.ichi2.anki.utils.navBarNeedsScrim @@ -85,6 +86,11 @@ class ReviewerFragment : } } + viewModel.actionFeedbackFlow.flowWithLifecycle(lifecycle) + .collectIn(lifecycleScope) { message -> + showSnackbar(message, duration = 500) + } + viewModel.isQueueFinishedFlow.collectIn(lifecycleScope) { isQueueFinished -> if (isQueueFinished) { requireActivity().run { @@ -106,6 +112,7 @@ class ReviewerFragment : when (item.itemId) { R.id.action_add_note -> launchAddNote() R.id.action_card_info -> launchCardInfo() + R.id.action_delete -> viewModel.deleteNote() R.id.action_edit -> launchEditNote() R.id.action_mark -> viewModel.toggleMark() R.id.action_open_deck_options -> launchDeckOptions() diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt index 560be447fdbb..151732b55c77 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt @@ -20,6 +20,7 @@ import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewmodel.initializer import androidx.lifecycle.viewmodel.viewModelFactory import anki.frontend.SetSchedulingStatesRequest +import com.ichi2.anki.CollectionManager import com.ichi2.anki.CollectionManager.withCol import com.ichi2.anki.Ease import com.ichi2.anki.NoteEditor @@ -56,6 +57,7 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( } var isQueueFinishedFlow = MutableSharedFlow() val isMarkedFlow = MutableStateFlow(false) + val actionFeedbackFlow = MutableSharedFlow() override val server = AnkiServer(this).also { it.start() } private val stateMutationKey = TimeManager.time.intTimeMS().toString() @@ -151,6 +153,17 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( } } + fun deleteNote() { + launchCatchingIO { + val cardId = currentCard.await().id + val noteCount = undoableOp { + removeNotes(cids = listOf(cardId)) + }.count + actionFeedbackFlow.emit(CollectionManager.TR.browsingCardsDeleted(noteCount)) + updateCurrentCard() + } + } + /* ********************************************************************************************* *************************************** Internal methods *************************************** ********************************************************************************************* */ diff --git a/AnkiDroid/src/main/res/menu/reviewer2.xml b/AnkiDroid/src/main/res/menu/reviewer2.xml index 46b1bc3dab74..1bf5f20cdabd 100644 --- a/AnkiDroid/src/main/res/menu/reviewer2.xml +++ b/AnkiDroid/src/main/res/menu/reviewer2.xml @@ -41,4 +41,9 @@ android:title="@string/menu_add_note" android:icon="@drawable/ic_add" app:showAsAction="never"/> + \ No newline at end of file From 8f4b1e72dea032d7ad3f0078b291ccf3236401e7 Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com> Date: Mon, 27 May 2024 19:31:55 -0300 Subject: [PATCH 120/138] refactor: updateCurrentCard() to remove some of the indent --- .../ui/windows/reviewer/ReviewerViewModel.kt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt index 151732b55c77..5c913875dd4b 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt @@ -246,12 +246,16 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( sched.currentQueueState() } } - queueState.await()?.let { - currentCard = CompletableDeferred(it.topCard) - showQuestion() - loadAndPlaySounds(CardSide.QUESTION) - updateMarkedStatus() - } ?: isQueueFinishedFlow.emit(true) + val state = queueState.await() + if (state == null) { + isQueueFinishedFlow.emit(true) + return + } + + currentCard = CompletableDeferred(state.topCard) + showQuestion() + loadAndPlaySounds(CardSide.QUESTION) + updateMarkedStatus() } // TODO From c7734d57b3e3f68752c4bcafaeeea26d6ef2c295 Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com> Date: Mon, 27 May 2024 19:38:24 -0300 Subject: [PATCH 121/138] feat(new reviewer): bury --- .../ichi2/anki/servicelayer/NoteService.kt | 10 ++++++ .../ui/windows/reviewer/ReviewerFragment.kt | 15 +++++++++ .../ui/windows/reviewer/ReviewerViewModel.kt | 31 ++++++++++++++++++- AnkiDroid/src/main/res/menu/reviewer2.xml | 19 ++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/NoteService.kt b/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/NoteService.kt index 26fac1a189ae..2ddcf2665a1b 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/NoteService.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/NoteService.kt @@ -242,3 +242,13 @@ fun Card.totalLapsesOfNote(col: Collection) = NoteService.totalLapses(col, note( fun Card.totalReviewsForNote(col: Collection) = NoteService.totalReviews(col, note(col)) fun Card.avgIntervalOfNote(col: Collection) = NoteService.avgInterval(col, note(col)) + +suspend fun isBuryNoteAvailable(card: Card): Boolean { + return withCol { + db.queryScalar( + "select 1 from cards where nid = ? and id != ? and queue >= " + Consts.QUEUE_TYPE_NEW + " limit 1", + card.nid, + card.id + ) == 1 + } +} diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt index 7c263f1c3804..4b8040ecd029 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt @@ -111,6 +111,8 @@ class ReviewerFragment : override fun onMenuItemClick(item: MenuItem): Boolean { when (item.itemId) { R.id.action_add_note -> launchAddNote() + R.id.action_bury_card -> viewModel.buryCard() + R.id.action_bury_note -> viewModel.buryNote() R.id.action_card_info -> launchCardInfo() R.id.action_delete -> viewModel.deleteNote() R.id.action_edit -> launchEditNote() @@ -166,6 +168,19 @@ class ReviewerFragment : markItem.setTitle(R.string.menu_mark_note) } } + + val buryItem = menu.findItem(R.id.action_bury) + val buryCardItem = menu.findItem(R.id.action_bury_card) + viewModel.canBuryNoteFlow.flowWithLifecycle(lifecycle) + .collectLatestIn(lifecycleScope) { canBuryNote -> + if (canBuryNote) { + buryItem.isVisible = true + buryCardItem.isVisible = false + } else { + buryItem.isVisible = false + buryCardItem.isVisible = true + } + } } private val noteEditorLauncher = diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt index 5c913875dd4b..651a762f6e83 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt @@ -35,6 +35,8 @@ 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 +import com.ichi2.anki.servicelayer.isBuryNoteAvailable +import com.ichi2.anki.servicelayer.isSuspendNoteAvailable import com.ichi2.libanki.hasTag import com.ichi2.libanki.note import com.ichi2.libanki.sched.CurrentQueueState @@ -58,6 +60,8 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( var isQueueFinishedFlow = MutableSharedFlow() val isMarkedFlow = MutableStateFlow(false) val actionFeedbackFlow = MutableSharedFlow() + val canBuryNoteFlow = MutableStateFlow(true) + val canSuspendNoteFlow = MutableStateFlow(true) override val server = AnkiServer(this).also { it.start() } private val stateMutationKey = TimeManager.time.intTimeMS().toString() @@ -164,6 +168,28 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( } } + fun buryCard() { + launchCatchingIO { + val cardId = currentCard.await().id + val noteCount = undoableOp { + sched.buryCards(cids = listOf(cardId)) + }.count + actionFeedbackFlow.emit(CollectionManager.TR.studyingCardsBuried(noteCount)) + updateCurrentCard() + } + } + + fun buryNote() { + launchCatchingIO { + val noteId = currentCard.await().nid + val noteCount = undoableOp { + sched.buryNotes(nids = listOf(noteId)) + }.count + actionFeedbackFlow.emit(CollectionManager.TR.studyingCardsBuried(noteCount)) + updateCurrentCard() + } + } + /* ********************************************************************************************* *************************************** Internal methods *************************************** ********************************************************************************************* */ @@ -252,10 +278,13 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( return } - currentCard = CompletableDeferred(state.topCard) + val card = state.topCard + currentCard = CompletableDeferred(card) showQuestion() loadAndPlaySounds(CardSide.QUESTION) updateMarkedStatus() + canBuryNoteFlow.emit(isBuryNoteAvailable(card)) + canSuspendNoteFlow.emit(isSuspendNoteAvailable(card)) } // TODO diff --git a/AnkiDroid/src/main/res/menu/reviewer2.xml b/AnkiDroid/src/main/res/menu/reviewer2.xml index 1bf5f20cdabd..98dc03467555 100644 --- a/AnkiDroid/src/main/res/menu/reviewer2.xml +++ b/AnkiDroid/src/main/res/menu/reviewer2.xml @@ -46,4 +46,23 @@ android:title="@string/menu_delete_note" android:icon="@drawable/ic_delete_white" app:showAsAction="never"/> + + + + + + + \ No newline at end of file From 6fc9a15a0b28dc3b8dcabfb10d0784bef20916ca Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com> Date: Mon, 27 May 2024 19:56:57 -0300 Subject: [PATCH 122/138] feat(new reviewer): suspend --- .../ichi2/anki/servicelayer/NoteService.kt | 10 +++++++++ .../ui/windows/reviewer/ReviewerFragment.kt | 15 +++++++++++++ .../ui/windows/reviewer/ReviewerViewModel.kt | 22 +++++++++++++++++++ AnkiDroid/src/main/res/menu/reviewer2.xml | 17 ++++++++++++++ 4 files changed, 64 insertions(+) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/NoteService.kt b/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/NoteService.kt index 2ddcf2665a1b..ee5fa223e9ff 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/NoteService.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/NoteService.kt @@ -252,3 +252,13 @@ suspend fun isBuryNoteAvailable(card: Card): Boolean { ) == 1 } } + +suspend fun isSuspendNoteAvailable(card: Card): Boolean { + return withCol { + db.queryScalar( + "select 1 from cards where nid = ? and id != ? and queue != " + Consts.QUEUE_TYPE_SUSPENDED + " limit 1", + card.nid, + card.id + ) == 1 + } +} diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt index 4b8040ecd029..7b28ec356975 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt @@ -118,6 +118,8 @@ class ReviewerFragment : R.id.action_edit -> launchEditNote() R.id.action_mark -> viewModel.toggleMark() R.id.action_open_deck_options -> launchDeckOptions() + R.id.action_suspend_card -> viewModel.suspendCard() + R.id.action_suspend_note -> viewModel.suspendNote() } return true } @@ -181,6 +183,19 @@ class ReviewerFragment : buryCardItem.isVisible = true } } + + val suspendItem = menu.findItem(R.id.action_suspend) + val suspendCardItem = menu.findItem(R.id.action_suspend_card) + viewModel.canSuspendNoteFlow.flowWithLifecycle(lifecycle) + .collectLatestIn(lifecycleScope) { canSuspendNote -> + if (canSuspendNote) { + suspendItem.isVisible = true + suspendCardItem.isVisible = false + } else { + suspendItem.isVisible = false + suspendItem.isVisible = true + } + } } private val noteEditorLauncher = diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt index 651a762f6e83..61b75bf30a8a 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt @@ -190,6 +190,28 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( } } + fun suspendCard() { + launchCatchingIO { + val cardId = currentCard.await().id + undoableOp { + sched.suspendCards(ids = listOf(cardId)) + }.count + actionFeedbackFlow.emit(CollectionManager.TR.studyingCardSuspended()) + updateCurrentCard() + } + } + + fun suspendNote() { + launchCatchingIO { + val noteId = currentCard.await().nid + undoableOp { + sched.suspendNotes(ids = listOf(noteId)) + } + actionFeedbackFlow.emit(CollectionManager.TR.studyingNoteSuspended()) + updateCurrentCard() + } + } + /* ********************************************************************************************* *************************************** Internal methods *************************************** ********************************************************************************************* */ diff --git a/AnkiDroid/src/main/res/menu/reviewer2.xml b/AnkiDroid/src/main/res/menu/reviewer2.xml index 98dc03467555..7b64ccc43606 100644 --- a/AnkiDroid/src/main/res/menu/reviewer2.xml +++ b/AnkiDroid/src/main/res/menu/reviewer2.xml @@ -65,4 +65,21 @@ android:title="@string/menu_bury_note" /> + + + + + + + \ No newline at end of file From e5a9652def88a5e4f821e1d9d229cec9a23d7faf Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com> Date: Mon, 27 May 2024 20:33:16 -0300 Subject: [PATCH 123/138] feat(new reviewer): user action --- .../src/main/assets/scripts/ankidroid.js | 13 +++++ .../ichi2/anki/previewer/PreviewerHelpers.kt | 4 +- .../ui/windows/reviewer/ReviewerFragment.kt | 9 ++++ .../ui/windows/reviewer/ReviewerViewModel.kt | 7 +++ AnkiDroid/src/main/res/menu/reviewer2.xml | 54 +++++++++++++++++++ 5 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 AnkiDroid/src/main/assets/scripts/ankidroid.js diff --git a/AnkiDroid/src/main/assets/scripts/ankidroid.js b/AnkiDroid/src/main/assets/scripts/ankidroid.js new file mode 100644 index 000000000000..5cf49c6085ae --- /dev/null +++ b/AnkiDroid/src/main/assets/scripts/ankidroid.js @@ -0,0 +1,13 @@ +"use strict"; +globalThis.ankidroid = globalThis.ankidroid || {}; + +globalThis.ankidroid.userAction = function (number) { + try { + let userJs = globalThis[`userJs${number}`]; + if (userJs != null) { + userJs(); + } + } catch (e) { + alert(e); + } +}; diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerHelpers.kt b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerHelpers.kt index 62e38ad0bc23..1275355d22f9 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerHelpers.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerHelpers.kt @@ -36,7 +36,7 @@ class NoteEditorDestination(val cardId: Long) { /** * Not exactly equal to anki's stdHtml. Some differences: - * * `ankidroid.css` is added + * * `ankidroid.css` and `ankidroid.js` are added * * `bridgeCommand()` is ignored * * Aimed to be used only for reviewing/previewing cards @@ -77,7 +77,6 @@ fun stdHtml( ":root[class*=night-mode] { --canvas: $canvasColor; --fg: $fgColor; }" } - @Suppress("UnnecessaryVariable") // necessary for the HTML notation @Language("HTML") val html = """ @@ -98,6 +97,7 @@ fun stdHtml(
+ diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt index 7b28ec356975..c5a882d679f8 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt @@ -120,6 +120,15 @@ class ReviewerFragment : R.id.action_open_deck_options -> launchDeckOptions() R.id.action_suspend_card -> viewModel.suspendCard() R.id.action_suspend_note -> viewModel.suspendNote() + R.id.user_action_1 -> viewModel.userAction(1) + R.id.user_action_2 -> viewModel.userAction(2) + R.id.user_action_3 -> viewModel.userAction(3) + R.id.user_action_4 -> viewModel.userAction(4) + R.id.user_action_5 -> viewModel.userAction(5) + R.id.user_action_6 -> viewModel.userAction(6) + R.id.user_action_7 -> viewModel.userAction(7) + R.id.user_action_8 -> viewModel.userAction(8) + R.id.user_action_9 -> viewModel.userAction(9) } return true } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt index 61b75bf30a8a..582df45eea72 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt @@ -24,6 +24,7 @@ import com.ichi2.anki.CollectionManager import com.ichi2.anki.CollectionManager.withCol import com.ichi2.anki.Ease import com.ichi2.anki.NoteEditor +import com.ichi2.anki.Reviewer import com.ichi2.anki.asyncIO import com.ichi2.anki.cardviewer.CardMediaPlayer import com.ichi2.anki.launchCatchingIO @@ -212,6 +213,12 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( } } + fun userAction(@Reviewer.UserAction number: Int) { + launchCatchingIO { + eval.emit("javascript: ankidroid.userAction($number);") + } + } + /* ********************************************************************************************* *************************************** Internal methods *************************************** ********************************************************************************************* */ diff --git a/AnkiDroid/src/main/res/menu/reviewer2.xml b/AnkiDroid/src/main/res/menu/reviewer2.xml index 7b64ccc43606..5164cf079711 100644 --- a/AnkiDroid/src/main/res/menu/reviewer2.xml +++ b/AnkiDroid/src/main/res/menu/reviewer2.xml @@ -82,4 +82,58 @@ android:title="@string/menu_suspend_note" />
+ + + + + + + + + \ No newline at end of file From 700ee53e17c58411acf1874dee01c28d2638c7a4 Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com> Date: Mon, 27 May 2024 21:09:00 -0300 Subject: [PATCH 124/138] feat(new reviewer): undo and redo --- .../ui/windows/reviewer/ReviewerFragment.kt | 17 ++++++ .../ui/windows/reviewer/ReviewerViewModel.kt | 56 ++++++++++++++++++- AnkiDroid/src/main/res/menu/reviewer2.xml | 15 ++++- 3 files changed, 86 insertions(+), 2 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt index c5a882d679f8..8e2395b0de8c 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt @@ -34,6 +34,7 @@ import androidx.lifecycle.lifecycleScope import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.button.MaterialButton import com.ichi2.anki.AbstractFlashcardViewer.Companion.RESULT_NO_MORE_CARDS +import com.ichi2.anki.CollectionManager import com.ichi2.anki.NoteEditor import com.ichi2.anki.R import com.ichi2.anki.cardviewer.CardMediaPlayer @@ -118,8 +119,10 @@ class ReviewerFragment : R.id.action_edit -> launchEditNote() R.id.action_mark -> viewModel.toggleMark() R.id.action_open_deck_options -> launchDeckOptions() + R.id.action_redo -> viewModel.redo() R.id.action_suspend_card -> viewModel.suspendCard() R.id.action_suspend_note -> viewModel.suspendNote() + R.id.action_undo -> viewModel.undo() R.id.user_action_1 -> viewModel.userAction(1) R.id.user_action_2 -> viewModel.userAction(2) R.id.user_action_3 -> viewModel.userAction(3) @@ -205,6 +208,20 @@ class ReviewerFragment : suspendItem.isVisible = true } } + + val undoItem = menu.findItem(R.id.action_undo) + viewModel.undoLabelFlow.flowWithLifecycle(lifecycle) + .collectLatestIn(lifecycleScope) { label -> + undoItem.title = label ?: CollectionManager.TR.undoUndo() + undoItem.isEnabled = label != null + } + + val redoItem = menu.findItem(R.id.action_redo) + viewModel.redoLabelFlow.flowWithLifecycle(lifecycle) + .collectLatestIn(lifecycleScope) { label -> + redoItem.title = label ?: CollectionManager.TR.undoRedo() + redoItem.isEnabled = label != null + } } private val noteEditorLauncher = diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt index 582df45eea72..8ca532768468 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt @@ -19,6 +19,7 @@ import androidx.activity.result.ActivityResult import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewmodel.initializer import androidx.lifecycle.viewmodel.viewModelFactory +import anki.collection.OpChanges import anki.frontend.SetSchedulingStatesRequest import com.ichi2.anki.CollectionManager import com.ichi2.anki.CollectionManager.withCol @@ -38,9 +39,12 @@ import com.ichi2.anki.servicelayer.MARKED_TAG import com.ichi2.anki.servicelayer.NoteService import com.ichi2.anki.servicelayer.isBuryNoteAvailable import com.ichi2.anki.servicelayer.isSuspendNoteAvailable +import com.ichi2.libanki.ChangeManager import com.ichi2.libanki.hasTag import com.ichi2.libanki.note +import com.ichi2.libanki.redo import com.ichi2.libanki.sched.CurrentQueueState +import com.ichi2.libanki.undo import com.ichi2.libanki.undoableOp import com.ichi2.libanki.utils.TimeManager import kotlinx.coroutines.CompletableDeferred @@ -49,7 +53,9 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow -class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel(cardMediaPlayer) { +class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : + CardViewerViewModel(cardMediaPlayer), + ChangeManager.Subscriber { private var queueState: Deferred = asyncIO { // this assumes that the Reviewer won't be launched if there isn't a queueState @@ -63,6 +69,8 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( val actionFeedbackFlow = MutableSharedFlow() val canBuryNoteFlow = MutableStateFlow(true) val canSuspendNoteFlow = MutableStateFlow(true) + val undoLabelFlow = MutableStateFlow(null) + val redoLabelFlow = MutableStateFlow(null) override val server = AnkiServer(this).also { it.start() } private val stateMutationKey = TimeManager.time.intTimeMS().toString() @@ -83,6 +91,13 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( */ private var statesMutated = true + init { + ChangeManager.subscribe(this) + launchCatchingIO { + updateUndoAndRedoLabels() + } + } + /* ********************************************************************************************* ************************ Public methods: meant to be used by the View ************************** ********************************************************************************************* */ @@ -213,6 +228,36 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( } } + fun undo() { + launchCatchingIO { + val changes = undoableOp { + undo() + } + val message = if (changes.operation.isEmpty()) { + CollectionManager.TR.actionsNothingToUndo() + } else { + CollectionManager.TR.undoActionUndone(changes.operation) + } + actionFeedbackFlow.emit(message) + updateCurrentCard() + } + } + + fun redo() { + launchCatchingIO { + val changes = undoableOp { + redo() + } + val message = if (changes.operation.isEmpty()) { + CollectionManager.TR.actionsNothingToRedo() + } else { + CollectionManager.TR.undoRedoAction(changes.operation) + } + actionFeedbackFlow.emit(message) + updateCurrentCard() + } + } + fun userAction(@Reviewer.UserAction number: Int) { launchCatchingIO { eval.emit("javascript: ankidroid.userAction($number);") @@ -321,6 +366,15 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : CardViewerViewModel( return text } + private suspend fun updateUndoAndRedoLabels() { + undoLabelFlow.emit(withCol { undoLabel() }) + redoLabelFlow.emit(withCol { redoLabel() }) + } + + override fun opExecuted(changes: OpChanges, handler: Any?) { + launchCatchingIO { updateUndoAndRedoLabels() } + } + companion object { fun factory(soundPlayer: CardMediaPlayer): ViewModelProvider.Factory { return viewModelFactory { diff --git a/AnkiDroid/src/main/res/menu/reviewer2.xml b/AnkiDroid/src/main/res/menu/reviewer2.xml index 5164cf079711..22c1fb6466b5 100644 --- a/AnkiDroid/src/main/res/menu/reviewer2.xml +++ b/AnkiDroid/src/main/res/menu/reviewer2.xml @@ -15,7 +15,20 @@ ~ this program. If not, see . --> + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> + + Date: Thu, 20 Jun 2024 11:37:24 -0300 Subject: [PATCH 125/138] refactor: define flags ids statically It is technically possible (although unlikely) to get an ID conflicts when using the ordinals as IDs. Also, I think that `onMenuItemClick` is easier to follow this way. --- .../src/main/java/com/ichi2/anki/Flag.kt | 24 ++++++++++------- .../ichi2/anki/previewer/PreviewerFragment.kt | 17 ++++++------ AnkiDroid/src/main/res/values/ids.xml | 26 +++++++++++++++++++ 3 files changed, 50 insertions(+), 17 deletions(-) create mode 100644 AnkiDroid/src/main/res/values/ids.xml diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt b/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt index 83fef3b6b90f..8674ace86acc 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/Flag.kt @@ -17,6 +17,7 @@ package com.ichi2.anki import androidx.annotation.ColorRes import androidx.annotation.DrawableRes +import androidx.annotation.IdRes import com.ichi2.anki.CollectionManager.TR import com.ichi2.anki.CollectionManager.withCol import com.ichi2.anki.utils.ext.getStringOrNull @@ -26,15 +27,20 @@ import com.ichi2.libanki.Collection import org.json.JSONObject import timber.log.Timber -enum class Flag(val code: Int, @DrawableRes val drawableRes: Int, @ColorRes val browserColorRes: Int?) { - NONE(0, R.drawable.ic_flag_transparent, null), - RED(1, R.drawable.ic_flag_red, R.color.flag_red), - ORANGE(2, R.drawable.ic_flag_orange, R.color.flag_orange), - GREEN(3, R.drawable.ic_flag_green, R.color.flag_green), - BLUE(4, R.drawable.ic_flag_blue, R.color.flag_blue), - PINK(5, R.drawable.ic_flag_pink, R.color.flag_pink), - TURQUOISE(6, R.drawable.ic_flag_turquoise, R.color.flag_turquoise), - PURPLE(7, R.drawable.ic_flag_purple, R.color.flag_purple); +enum class Flag( + val code: Int, + @IdRes val id: Int, + @DrawableRes val drawableRes: Int, + @ColorRes val browserColorRes: Int? +) { + NONE(0, R.id.flag_none, R.drawable.ic_flag_transparent, null), + RED(1, R.id.flag_red, R.drawable.ic_flag_red, R.color.flag_red), + ORANGE(2, R.id.flag_orange, R.drawable.ic_flag_orange, R.color.flag_orange), + GREEN(3, R.id.flag_green, R.drawable.ic_flag_green, R.color.flag_green), + BLUE(4, R.id.flag_blue, R.drawable.ic_flag_blue, R.color.flag_blue), + PINK(5, R.id.flag_pink, R.drawable.ic_flag_pink, R.color.flag_pink), + TURQUOISE(6, R.id.flag_turquoise, R.drawable.ic_flag_turquoise, R.color.flag_turquoise), + PURPLE(7, R.id.flag_purple, R.drawable.ic_flag_purple, R.color.flag_purple); /** * Retrieves the name associated with the flag. This may be user-defined diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerFragment.kt index b5567e279e06..8f8826419edd 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/previewer/PreviewerFragment.kt @@ -50,7 +50,6 @@ import com.ichi2.annotations.NeedsTest import com.ichi2.utils.performClickIfEnabled import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch -import timber.log.Timber class PreviewerFragment : CardViewerFragment(R.layout.previewer), @@ -194,23 +193,25 @@ class PreviewerFragment : val submenu = menu.findItem(R.id.action_flag).subMenu lifecycleScope.launch { for ((flag, name) in Flag.queryDisplayNames()) { - submenu?.add(Menu.NONE, flag.ordinal, Menu.NONE, name) + submenu?.add(Menu.NONE, flag.id, Menu.NONE, name) ?.setIcon(flag.drawableRes) } } } override fun onMenuItemClick(item: MenuItem): Boolean { - Flag.entries.find { it.ordinal == item.itemId }?.let { flag -> - Timber.i("PreviewerFragment:: onMenuItemClick Flag - ${flag.name} clicked") - viewModel.setFlag(flag) - return true - } - when (item.itemId) { R.id.action_edit -> editCard() R.id.action_mark -> viewModel.toggleMark() R.id.action_back_side_only -> viewModel.toggleBackSideOnly() + R.id.flag_none -> viewModel.setFlag(Flag.NONE) + R.id.flag_red -> viewModel.setFlag(Flag.RED) + R.id.flag_orange -> viewModel.setFlag(Flag.ORANGE) + R.id.flag_green -> viewModel.setFlag(Flag.GREEN) + R.id.flag_blue -> viewModel.setFlag(Flag.BLUE) + R.id.flag_pink -> viewModel.setFlag(Flag.PINK) + R.id.flag_turquoise -> viewModel.setFlag(Flag.TURQUOISE) + R.id.flag_purple -> viewModel.setFlag(Flag.PURPLE) } return true } diff --git a/AnkiDroid/src/main/res/values/ids.xml b/AnkiDroid/src/main/res/values/ids.xml new file mode 100644 index 000000000000..e599a2daa65c --- /dev/null +++ b/AnkiDroid/src/main/res/values/ids.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + \ No newline at end of file From 8ab378ca80b21efdd56f53f075fc346beda3ecaa Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com> Date: Thu, 20 Jun 2024 11:40:10 -0300 Subject: [PATCH 126/138] feat(new reviewer): flags --- .../ui/windows/reviewer/ReviewerFragment.kt | 26 +++++++++++++++++++ .../ui/windows/reviewer/ReviewerViewModel.kt | 13 ++++++++++ AnkiDroid/src/main/res/menu/reviewer2.xml | 10 +++++++ 3 files changed, 49 insertions(+) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt index 8e2395b0de8c..0d9697b46d25 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt @@ -35,6 +35,7 @@ import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.button.MaterialButton import com.ichi2.anki.AbstractFlashcardViewer.Companion.RESULT_NO_MORE_CARDS import com.ichi2.anki.CollectionManager +import com.ichi2.anki.Flag import com.ichi2.anki.NoteEditor import com.ichi2.anki.R import com.ichi2.anki.cardviewer.CardMediaPlayer @@ -123,6 +124,14 @@ class ReviewerFragment : R.id.action_suspend_card -> viewModel.suspendCard() R.id.action_suspend_note -> viewModel.suspendNote() R.id.action_undo -> viewModel.undo() + R.id.flag_none -> viewModel.setFlag(Flag.NONE) + R.id.flag_red -> viewModel.setFlag(Flag.RED) + R.id.flag_orange -> viewModel.setFlag(Flag.ORANGE) + R.id.flag_green -> viewModel.setFlag(Flag.GREEN) + R.id.flag_blue -> viewModel.setFlag(Flag.BLUE) + R.id.flag_pink -> viewModel.setFlag(Flag.PINK) + R.id.flag_turquoise -> viewModel.setFlag(Flag.TURQUOISE) + R.id.flag_purple -> viewModel.setFlag(Flag.PURPLE) R.id.user_action_1 -> viewModel.userAction(1) R.id.user_action_2 -> viewModel.userAction(2) R.id.user_action_3 -> viewModel.userAction(3) @@ -169,7 +178,24 @@ class ReviewerFragment : } } + private fun setupFlagMenu(menu: Menu) { + val submenu = menu.findItem(R.id.action_flag).subMenu + lifecycleScope.launch { + for ((flag, name) in Flag.queryDisplayNames()) { + submenu?.add(Menu.NONE, flag.id, Menu.NONE, name) + ?.setIcon(flag.drawableRes) + } + } + + viewModel.flagCodeFlow.flowWithLifecycle(lifecycle) + .collectLatestIn(lifecycleScope) { flagCode -> + menu.findItem(R.id.action_flag).setIcon(Flag.fromCode(flagCode).drawableRes) + } + } + private fun setupMenuItems(menu: Menu) { + setupFlagMenu(menu) + // TODO show that the card is marked somehow when the menu item is overflowed or not shown val markItem = menu.findItem(R.id.action_mark) viewModel.isMarkedFlow.flowWithLifecycle(lifecycle) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt index 8ca532768468..d1ba5f9c4b97 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt @@ -24,6 +24,7 @@ import anki.frontend.SetSchedulingStatesRequest import com.ichi2.anki.CollectionManager import com.ichi2.anki.CollectionManager.withCol import com.ichi2.anki.Ease +import com.ichi2.anki.Flag import com.ichi2.anki.NoteEditor import com.ichi2.anki.Reviewer import com.ichi2.anki.asyncIO @@ -66,6 +67,7 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : } var isQueueFinishedFlow = MutableSharedFlow() val isMarkedFlow = MutableStateFlow(false) + val flagCodeFlow = MutableStateFlow(Flag.NONE.code) val actionFeedbackFlow = MutableSharedFlow() val canBuryNoteFlow = MutableStateFlow(true) val canSuspendNoteFlow = MutableStateFlow(true) @@ -139,6 +141,16 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : } } + fun setFlag(flag: Flag) { + launchCatchingIO { + val card = currentCard.await() + undoableOp { + setUserFlagForCards(listOf(card.id), flag.code) + } + flagCodeFlow.emit(flag.code) + } + } + fun onStateMutationCallback() { statesMutated = true } @@ -357,6 +369,7 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : showQuestion() loadAndPlaySounds(CardSide.QUESTION) updateMarkedStatus() + flagCodeFlow.emit(card.userFlag()) canBuryNoteFlow.emit(isBuryNoteAvailable(card)) canSuspendNoteFlow.emit(isSuspendNoteAvailable(card)) } diff --git a/AnkiDroid/src/main/res/menu/reviewer2.xml b/AnkiDroid/src/main/res/menu/reviewer2.xml index 22c1fb6466b5..f58f78c5a4d8 100644 --- a/AnkiDroid/src/main/res/menu/reviewer2.xml +++ b/AnkiDroid/src/main/res/menu/reviewer2.xml @@ -29,6 +29,16 @@ android:icon="@drawable/ic_redo" tools:title="Redo" app:showAsAction="never"/> + + + + + Date: Thu, 20 Jun 2024 11:48:03 -0300 Subject: [PATCH 127/138] refactor: handleNoteEditorResult and handleDeckOptionsResult --- .../ui/windows/reviewer/ReviewerFragment.kt | 8 ++++++-- .../ui/windows/reviewer/ReviewerViewModel.kt | 18 +++--------------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt index 0d9697b46d25..3e46527dc926 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt @@ -252,7 +252,11 @@ class ReviewerFragment : private val noteEditorLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - viewModel.handleNoteEditorResult(result) + if (result.data?.getBooleanExtra(NoteEditor.RELOAD_REQUIRED_EXTRA_KEY, false) == true || + result.data?.getBooleanExtra(NoteEditor.NOTE_CHANGED_EXTRA_KEY, false) == true + ) { + viewModel.refreshCard() + } } private fun launchEditNote() { @@ -277,7 +281,7 @@ class ReviewerFragment : } private val deckOptionsLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { - viewModel.handleDeckOptionsResult() + viewModel.refreshCard() } private fun launchDeckOptions() { diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt index d1ba5f9c4b97..02679dc28456 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt @@ -15,7 +15,6 @@ */ package com.ichi2.anki.ui.windows.reviewer -import androidx.activity.result.ActivityResult import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewmodel.initializer import androidx.lifecycle.viewmodel.viewModelFactory @@ -25,7 +24,6 @@ import com.ichi2.anki.CollectionManager import com.ichi2.anki.CollectionManager.withCol import com.ichi2.anki.Ease import com.ichi2.anki.Flag -import com.ichi2.anki.NoteEditor import com.ichi2.anki.Reviewer import com.ichi2.anki.asyncIO import com.ichi2.anki.cardviewer.CardMediaPlayer @@ -159,13 +157,9 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : return NoteEditorDestination(currentCard.await().id) } - fun handleNoteEditorResult(result: ActivityResult) { - if (result.data?.getBooleanExtra(NoteEditor.RELOAD_REQUIRED_EXTRA_KEY, false) == true || - result.data?.getBooleanExtra(NoteEditor.NOTE_CHANGED_EXTRA_KEY, false) == true - ) { - launchCatchingIO { - updateCurrentCard() - } + fun refreshCard() { + launchCatchingIO { + updateCurrentCard() } } @@ -179,12 +173,6 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : return DeckOptionsDestination(deckId, isFiltered) } - fun handleDeckOptionsResult() { - launchCatchingIO { - updateCurrentCard() - } - } - fun deleteNote() { launchCatchingIO { val cardId = currentCard.await().id From 16c23cf16755f48cf76279c8575c28b7a903ac97 Mon Sep 17 00:00:00 2001 From: snowtimeglass Date: Fri, 21 Jun 2024 18:34:35 +0900 Subject: [PATCH 128/138] Rename "Cancel" of Media Sync to "Abort" - in "Media Sync Log" dialog box and in "Syncing media" notification - The use of "Abort" in the dialog box is consistency with Anki Desktop. --- AnkiDroid/src/main/java/com/ichi2/anki/Sync.kt | 2 +- .../src/main/java/com/ichi2/anki/worker/SyncMediaWorker.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Sync.kt b/AnkiDroid/src/main/java/com/ichi2/anki/Sync.kt index 1e74bb490114..3b587982092f 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/Sync.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/Sync.kt @@ -366,7 +366,7 @@ suspend fun monitorMediaSync( .setPositiveButton(R.string.dialog_continue) { _, _ -> scope.cancel() } - .setNegativeButton(R.string.dialog_cancel) { _, _ -> + .setNegativeButton(TR.syncAbortButton()) { _, _ -> cancelMediaSync(backend) } .show() diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/worker/SyncMediaWorker.kt b/AnkiDroid/src/main/java/com/ichi2/anki/worker/SyncMediaWorker.kt index b4bc1e613e94..cc0d6b16eb64 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/worker/SyncMediaWorker.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/worker/SyncMediaWorker.kt @@ -113,7 +113,7 @@ class SyncMediaWorker( override suspend fun getForegroundInfo(): ForegroundInfo { val title = applicationContext.getString(R.string.syncing_media) - val cancelTitle = applicationContext.getString(R.string.dialog_cancel) + val cancelTitle = CollectionManager.TR.syncAbortButton() val notification = buildNotification { setContentTitle(title) setOngoing(true) @@ -148,7 +148,7 @@ class SyncMediaWorker( private fun getProgressNotification(progress: CharSequence): Notification { val title = applicationContext.getString(R.string.syncing_media) - val cancelTitle = applicationContext.getString(R.string.dialog_cancel) + val cancelTitle = CollectionManager.TR.syncAbortButton() return buildNotification { setContentTitle(title) From 8b196f6f68da529c3465ef5cd7d03f941eb9fcce Mon Sep 17 00:00:00 2001 From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com> Date: Sat, 22 Jun 2024 05:39:14 -0300 Subject: [PATCH 129/138] feat(new reviewer): counts --- .../ui/windows/reviewer/ReviewerFragment.kt | 27 ++++++++++++++ .../ui/windows/reviewer/ReviewerViewModel.kt | 3 ++ AnkiDroid/src/main/res/layout/reviewer2.xml | 35 ++++++++++++++++++- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt index 3e46527dc926..e24b9b57d7bd 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerFragment.kt @@ -18,6 +18,8 @@ package com.ichi2.anki.ui.windows.reviewer import android.content.Context import android.content.Intent import android.os.Bundle +import android.text.SpannableString +import android.text.style.UnderlineSpan import android.view.Menu import android.view.MenuItem import android.view.View @@ -33,6 +35,7 @@ import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.button.MaterialButton +import com.google.android.material.textview.MaterialTextView import com.ichi2.anki.AbstractFlashcardViewer.Companion.RESULT_NO_MORE_CARDS import com.ichi2.anki.CollectionManager import com.ichi2.anki.Flag @@ -47,6 +50,7 @@ import com.ichi2.anki.snackbar.showSnackbar import com.ichi2.anki.utils.ext.collectIn import com.ichi2.anki.utils.ext.collectLatestIn import com.ichi2.anki.utils.navBarNeedsScrim +import com.ichi2.libanki.sched.Counts import com.ichi2.utils.increaseHorizontalPaddingOfOverflowMenuIcons import kotlinx.coroutines.launch @@ -70,6 +74,7 @@ class ReviewerFragment : super.onViewCreated(view, savedInstanceState) setupAnswerButtons(view) + setupCounts(view) view.findViewById(R.id.toolbar).apply { setOnMenuItemClickListener(this@ReviewerFragment) @@ -178,6 +183,28 @@ class ReviewerFragment : } } + private fun setupCounts(view: View) { + val newCount = view.findViewById(R.id.new_count) + val learnCount = view.findViewById(R.id.lrn_count) + val reviewCount = view.findViewById(R.id.rev_count) + + viewModel.countsFlow.flowWithLifecycle(lifecycle) + .collectLatestIn(lifecycleScope) { (counts, countsType) -> + newCount.text = counts.new.toString() + learnCount.text = counts.lrn.toString() + reviewCount.text = counts.rev.toString() + + val currentCount = when (countsType) { + Counts.Queue.NEW -> newCount + Counts.Queue.LRN -> learnCount + Counts.Queue.REV -> reviewCount + } + val spannableString = SpannableString(currentCount.text) + spannableString.setSpan(UnderlineSpan(), 0, currentCount.text.length, 0) + currentCount.text = spannableString + } + } + private fun setupFlagMenu(menu: Menu) { val submenu = menu.findItem(R.id.action_flag).subMenu lifecycleScope.launch { diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt index 02679dc28456..35f823cca03f 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt @@ -42,6 +42,7 @@ import com.ichi2.libanki.ChangeManager import com.ichi2.libanki.hasTag import com.ichi2.libanki.note import com.ichi2.libanki.redo +import com.ichi2.libanki.sched.Counts import com.ichi2.libanki.sched.CurrentQueueState import com.ichi2.libanki.undo import com.ichi2.libanki.undoableOp @@ -71,6 +72,7 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : val canSuspendNoteFlow = MutableStateFlow(true) val undoLabelFlow = MutableStateFlow(null) val redoLabelFlow = MutableStateFlow(null) + val countsFlow = MutableStateFlow(Counts() to Counts.Queue.NEW) override val server = AnkiServer(this).also { it.start() } private val stateMutationKey = TimeManager.time.intTimeMS().toString() @@ -360,6 +362,7 @@ class ReviewerViewModel(cardMediaPlayer: CardMediaPlayer) : flagCodeFlow.emit(card.userFlag()) canBuryNoteFlow.emit(isBuryNoteAvailable(card)) canSuspendNoteFlow.emit(isSuspendNoteAvailable(card)) + countsFlow.emit(state.counts to state.countsIndex) } // TODO diff --git a/AnkiDroid/src/main/res/layout/reviewer2.xml b/AnkiDroid/src/main/res/layout/reviewer2.xml index f2ed634dc489..5f5b525c008d 100644 --- a/AnkiDroid/src/main/res/layout/reviewer2.xml +++ b/AnkiDroid/src/main/res/layout/reviewer2.xml @@ -28,7 +28,40 @@ android:layout_height="wrap_content" android:background="?attr/alternativeBackgroundColor" app:menu="@menu/reviewer2" - /> + > + + + + + + + + + Date: Sun, 23 Jun 2024 18:49:00 +0530 Subject: [PATCH 130/138] Fix IDE Warning: Removing redundant qualifiers name (#16638) --- .../main/java/com/ichi2/anki/AnkiActivity.kt | 3 +-- .../java/com/ichi2/anki/CardBrowserTest.kt | 2 +- .../ichi2/anki/dialogs/tags/TagsDialogTest.kt | 25 +++++++++---------- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt index 15f492b74651..8cb7e3177c90 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt @@ -27,7 +27,6 @@ import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.widget.ThemeUtils import androidx.appcompat.widget.Toolbar import androidx.browser.customtabs.CustomTabColorSchemeParams -import androidx.browser.customtabs.CustomTabsIntent import androidx.browser.customtabs.CustomTabsIntent.* import androidx.core.app.NotificationCompat import androidx.core.app.PendingIntentCompat @@ -332,7 +331,7 @@ open class AnkiActivity : AppCompatActivity, SimpleMessageDialogListener { .setToolbarColor(toolbarColor) .setNavigationBarColor(navBarColor) .build() - val builder = CustomTabsIntent.Builder(customTabActivityHelper.session) + val builder = Builder(customTabActivityHelper.session) .setShowTitle(true) .setStartAnimations(this, R.anim.slide_right_in, R.anim.slide_left_out) .setExitAnimations(this, R.anim.slide_left_in, R.anim.slide_right_out) diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt index 55caf4e1618d..cc5e58fc95e9 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt @@ -1188,7 +1188,7 @@ class CardBrowserTest : RobolectricTest() { }.addNote("Test", "Blank") val question = CardCache(note.firstCard().id, col, 1, CARDS) - .getColumnHeaderText(CardBrowserColumn.QUESTION) + .getColumnHeaderText(QUESTION) assertThat(question, equalTo("")) } diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/tags/TagsDialogTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/tags/TagsDialogTest.kt index 0ea3e9884860..2d6f8a3c651b 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/tags/TagsDialogTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/tags/TagsDialogTest.kt @@ -40,7 +40,6 @@ import com.ichi2.testutils.ParametersUtils import com.ichi2.testutils.RecyclerViewUtils import com.ichi2.ui.CheckBoxTriStates import com.ichi2.utils.ListUtil -import org.hamcrest.MatcherAssert import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.core.IsNull import org.junit.Assert @@ -68,7 +67,7 @@ class TagsDialogTest : RobolectricTest() { scenario.moveToState(Lifecycle.State.STARTED) scenario.onFragment { f: TagsDialog -> val dialog = f.dialog as AlertDialog? - MatcherAssert.assertThat(dialog, IsNull.notNullValue()) + assertThat(dialog, IsNull.notNullValue()) val optionsGroup = dialog!!.findViewById(R.id.tags_dialog_options_radiogroup)!! Assert.assertEquals(optionsGroup.visibility.toLong(), View.VISIBLE.toLong()) @@ -91,7 +90,7 @@ class TagsDialogTest : RobolectricTest() { scenario.moveToState(Lifecycle.State.STARTED) scenario.onFragment { f: TagsDialog -> val dialog = f.dialog as AlertDialog? - MatcherAssert.assertThat(dialog, IsNull.notNullValue()) + assertThat(dialog, IsNull.notNullValue()) val returnedList = AtomicReference?>() val returnedOption = AtomicReference() f.parentFragmentManager.setFragmentResultListener( @@ -129,7 +128,7 @@ class TagsDialogTest : RobolectricTest() { scenario.moveToState(Lifecycle.State.STARTED) scenario.onFragment { f: TagsDialog -> val dialog = f.dialog as AlertDialog? - MatcherAssert.assertThat(dialog, IsNull.notNullValue()) + assertThat(dialog, IsNull.notNullValue()) val recycler: RecyclerView = dialog!!.findViewById(R.id.tags_dialog_tags_list)!! val tag = "zzzz" @@ -164,7 +163,7 @@ class TagsDialogTest : RobolectricTest() { scenario.moveToState(Lifecycle.State.STARTED) scenario.onFragment { f: TagsDialog -> val dialog = f.dialog as AlertDialog? - MatcherAssert.assertThat(dialog, IsNull.notNullValue()) + assertThat(dialog, IsNull.notNullValue()) val recycler: RecyclerView = dialog!!.findViewById(R.id.tags_dialog_tags_list)!! val tag = "e" @@ -202,7 +201,7 @@ class TagsDialogTest : RobolectricTest() { scenario.moveToState(Lifecycle.State.STARTED) scenario.onFragment { f: TagsDialog -> val dialog = f.dialog as AlertDialog? - MatcherAssert.assertThat(dialog, IsNull.notNullValue()) + assertThat(dialog, IsNull.notNullValue()) val recycler: RecyclerView = dialog!!.findViewById(R.id.tags_dialog_tags_list)!! @@ -257,7 +256,7 @@ class TagsDialogTest : RobolectricTest() { scenario.moveToState(Lifecycle.State.STARTED) scenario.onFragment { f: TagsDialog -> val dialog = f.dialog as AlertDialog? - MatcherAssert.assertThat(dialog, IsNull.notNullValue()) + assertThat(dialog, IsNull.notNullValue()) val recycler: RecyclerView = dialog!!.findViewById(R.id.tags_dialog_tags_list)!! @@ -304,7 +303,7 @@ class TagsDialogTest : RobolectricTest() { scenario.moveToState(Lifecycle.State.STARTED) scenario.onFragment { f: TagsDialog -> val dialog = f.dialog as AlertDialog? - MatcherAssert.assertThat(dialog, IsNull.notNullValue()) + assertThat(dialog, IsNull.notNullValue()) val recycler: RecyclerView = dialog!!.findViewById(R.id.tags_dialog_tags_list)!! val tag = "common::sport::football::small" @@ -358,7 +357,7 @@ class TagsDialogTest : RobolectricTest() { scenario.moveToState(Lifecycle.State.STARTED) scenario.onFragment { f: TagsDialog -> val dialog = f.dialog as AlertDialog? - MatcherAssert.assertThat(dialog, IsNull.notNullValue()) + assertThat(dialog, IsNull.notNullValue()) val recycler: RecyclerView = dialog!!.findViewById(R.id.tags_dialog_tags_list)!! val tag = "common::::careless" @@ -406,7 +405,7 @@ class TagsDialogTest : RobolectricTest() { scenario.moveToState(Lifecycle.State.STARTED) scenario.onFragment { f: TagsDialog -> val dialog = f.dialog as AlertDialog? - MatcherAssert.assertThat(dialog, IsNull.notNullValue()) + assertThat(dialog, IsNull.notNullValue()) val recycler: RecyclerView = dialog!!.findViewById(R.id.tags_dialog_tags_list)!! val adapter = recycler.adapter!! as TagsArrayAdapter @@ -447,7 +446,7 @@ class TagsDialogTest : RobolectricTest() { scenario.moveToState(Lifecycle.State.STARTED) scenario.onFragment { f: TagsDialog -> val dialog = f.dialog as AlertDialog? - MatcherAssert.assertThat(dialog, IsNull.notNullValue()) + assertThat(dialog, IsNull.notNullValue()) val recycler: RecyclerView = dialog!!.findViewById(R.id.tags_dialog_tags_list)!! @@ -494,7 +493,7 @@ class TagsDialogTest : RobolectricTest() { scenario.moveToState(Lifecycle.State.STARTED) scenario.onFragment { f: TagsDialog -> val dialog = f.dialog as AlertDialog? - MatcherAssert.assertThat(dialog, IsNull.notNullValue()) + assertThat(dialog, IsNull.notNullValue()) val recycler: RecyclerView = dialog!!.findViewById(R.id.tags_dialog_tags_list)!! @@ -613,7 +612,7 @@ class TagsDialogTest : RobolectricTest() { scenario.moveToState(Lifecycle.State.STARTED) scenario.onFragment { f: TagsDialog -> val dialog = f.dialog as AlertDialog? - MatcherAssert.assertThat(dialog, IsNull.notNullValue()) + assertThat(dialog, IsNull.notNullValue()) val editText = f.getSearchView()!!.findViewById(androidx.appcompat.R.id.search_src_text)!! editText.setText("hello ") From 07c4923407577881d052c52e20d7deeaf744ecbf Mon Sep 17 00:00:00 2001 From: David Allison <62114487+david-allison@users.noreply.github.com> Date: Sun, 23 Jun 2024 15:43:01 +0100 Subject: [PATCH 131/138] improvement: re-add import qualifier Removed in 301f0a152a3e17bc5664eaa08ea54ed9df26998a But 'Builder' is ambiguous --- AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt index 8cb7e3177c90..e10b2fda369d 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt @@ -56,6 +56,7 @@ import com.ichi2.themes.Themes import com.ichi2.utils.AdaptionUtil import com.ichi2.utils.KotlinCleanup import timber.log.Timber +import androidx.browser.customtabs.CustomTabsIntent.Builder as CustomTabsIntentBuilder @UiThread @KotlinCleanup("set activityName") @@ -331,7 +332,7 @@ open class AnkiActivity : AppCompatActivity, SimpleMessageDialogListener { .setToolbarColor(toolbarColor) .setNavigationBarColor(navBarColor) .build() - val builder = Builder(customTabActivityHelper.session) + val builder = CustomTabsIntentBuilder(customTabActivityHelper.session) .setShowTitle(true) .setStartAnimations(this, R.anim.slide_right_in, R.anim.slide_left_out) .setExitAnimations(this, R.anim.slide_left_in, R.anim.slide_right_out) From 1456d77dc37c835a0aba050ef2fa133aa2688974 Mon Sep 17 00:00:00 2001 From: Voczi Date: Sat, 22 Jun 2024 16:50:01 +0200 Subject: [PATCH 132/138] Switch from hardcoded signing config --- .github/workflows/compare_apk_size.yml | 16 ++++++---------- .github/workflows/publish.yml | 10 ++++++---- AnkiDroid/build.gradle | 6 +++--- tools/check-keystore.sh | 21 +++++++++++++++++++++ tools/local-release.sh | 10 +++------- tools/parallel-package-release.sh | 13 +++---------- tools/release.sh | 8 +------- 7 files changed, 43 insertions(+), 41 deletions(-) create mode 100644 tools/check-keystore.sh diff --git a/.github/workflows/compare_apk_size.yml b/.github/workflows/compare_apk_size.yml index 40409520cd0f..c61c189423dc 100644 --- a/.github/workflows/compare_apk_size.yml +++ b/.github/workflows/compare_apk_size.yml @@ -24,11 +24,9 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest env: - # could be better, '/home/runner' should be '~/' but neither that nor '$HOME' worked - STOREFILEDIR: /home/runner/src - STOREFILE: android-keystore - STOREPASS: testpass - KEYPASS: testpass + KEYSTORENAME: keystore + KEYSTOREPWD: testpass + KEYPWD: testpass KEYALIAS: nrkeystorealias steps: - name: Configure JDK @@ -39,11 +37,9 @@ jobs: - name: Test Credential Prep run: | - echo "KSTOREPWD=$STOREPASS" >> $GITHUB_ENV - echo "KEYPWD=$KEYPASS" >> $GITHUB_ENV - mkdir $STOREFILEDIR - cd $STOREFILEDIR - echo y | keytool -genkeypair -dname "cn=AnkiDroid, ou=ankidroid, o=AnkiDroid, c=US" -alias $KEYALIAS -keypass $KEYPASS -keystore "$STOREFILE" -storepass $STOREPASS -keyalg RSA -validity 20000 + export KEYSTOREPATH=$HOME/$KEYSTORENAME + echo "KEYSTOREPATH=$KEYSTOREPATH" >> $GITHUB_ENV + echo y | keytool -genkeypair -dname "cn=AnkiDroid, ou=ankidroid, o=AnkiDroid, c=US" -alias $KEYALIAS -keypass $KEYPWD -keystore $KEYSTOREPATH -storepass $KEYSTOREPWD -keyalg RSA -validity 20000 shell: bash - name: Setup Gradle diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index d4a064ee7dfc..75bb4acda34d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -53,15 +53,17 @@ jobs: - name: Credential Prep run: | - echo "KSTOREPWD=${{ secrets.KEYSTORE_PASSWORD }}" >> $GITHUB_ENV + export KEYSTOREPATH=$HOME/src/android-keystore + echo "KEYSTOREPATH=$KEYSTOREPATH" >> $GITHUB_ENV + echo "KEYALIAS=nrkeystorealias" >> $GITHUB_ENV + echo "KEYSTOREPWD=${{ secrets.KEYSTORE_PASSWORD }}" >> $GITHUB_ENV echo "KEYPWD=${{ secrets.KEYSTORE_KEY_PASSWORD }}" >> $GITHUB_ENV mkdir ~/src echo "${{ secrets.AMAZON_PUBLISH_CREDENTIALS }}" | base64 -d > ~/src/AnkiDroid-Amazon-Publish-Security-Profile.json.gz echo "${{ secrets.GOOGLE_PUBLISH_CREDENTIALS }}" | base64 -d > ~/src/AnkiDroid-GCP-Publish-Credentials.json.gz echo "${{ secrets.RELEASES_PUBLISH_TOKEN }}" | base64 -d > ~/src/my-github-personal-access-token.gz - echo "${{ secrets.KEYSTORE }}" | base64 -d > ~/src/android-keystore.gz - cd ~/src - gunzip *gz + echo "${{ secrets.KEYSTORE }}" | base64 -d > $KEYSTOREPATH.gz + gunzip $KEYSTOREPATH.gz shell: bash - name: Build and Release public release diff --git a/AnkiDroid/build.gradle b/AnkiDroid/build.gradle index 9c18e4117fa2..114b4513f345 100644 --- a/AnkiDroid/build.gradle +++ b/AnkiDroid/build.gradle @@ -85,9 +85,9 @@ android { } signingConfigs { release { - storeFile file("${homePath}/src/android-keystore") - keyAlias "nrkeystorealias" - storePassword System.getenv("KSTOREPWD") + storeFile file(System.getenv("KEYSTOREPATH") ?: "${homePath}/src/android-keystore") + storePassword System.getenv("KEYSTOREPWD") ?: System.getenv("KSTOREPWD") + keyAlias System.getenv("KEYALIAS") ?: "nrkeystorealias" keyPassword System.getenv("KEYPWD") } } diff --git a/tools/check-keystore.sh b/tools/check-keystore.sh new file mode 100644 index 000000000000..15af5a694ba3 --- /dev/null +++ b/tools/check-keystore.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +if [ "$KEYSTOREPATH" == "" ]; then + read -rsp "Enter keystore path: " KEYSTOREPATH; echo + export KEYSTOREPATH +fi + +if [ "$KEYSTOREPWD" == "" ]; then + read -rsp "Enter keystore password: " KEYSTOREPWD; echo + export KEYSTOREPWD +fi + +if [ "$KEYALIAS" == "" ]; then + read -rsp "Enter key alias: " KEYALIAS; echo + export KEYALIAS +fi + +if [ "$KEYPWD" == "" ]; then + read -rsp "Enter key password: " KEYPWD; echo + export KEYPWD +fi \ No newline at end of file diff --git a/tools/local-release.sh b/tools/local-release.sh index 5fb37a748793..91c3144c8c58 100755 --- a/tools/local-release.sh +++ b/tools/local-release.sh @@ -3,15 +3,11 @@ # This script assumes a few things - # # 1) you are in the main directory of the Anki source code (e.g. 'Anki-Android' is the current working directory) -# 2) you have a Java keystore at the file path $home/src/android-keystore -# 3) In that java keystore you have the key alias 'nrkeystorealias' +# 2) you have a Java keystore, with a keystore+key password and key alias # It will ask you for your keystore and key password -# Read the key passwords -read -sp "Enter keystore password: " KSTOREPWD; echo -read -sp "Enter key password: " KEYPWD; echo -export KSTOREPWD -export KEYPWD +. tools/check-keystore.sh + ./gradlew assembleRelease -Duniversal-apk=true ./tools/parallel-package-release.sh TEST diff --git a/tools/parallel-package-release.sh b/tools/parallel-package-release.sh index 20890d62c5fa..e7791e57ebe3 100755 --- a/tools/parallel-package-release.sh +++ b/tools/parallel-package-release.sh @@ -3,9 +3,8 @@ # This script assumes a few things - # # 1) you are in the main directory of the Anki source code (e.g. 'Anki-Android' is the current working directory) -# 2) you have a Java keystore at the file path $home/src/android-keystore -# 3) In that java keystore you have the key alias 'nrkeystorealias' -# 4) you have no local changes in your working directory (e.g. "git reset --hard && git clean -f") +# 2) you have a Java keystore, with a keystore+key password and key alias +# 3) you have no local changes in your working directory (e.g. "git reset --hard && git clean -f") # If those assumptions are met, this script will generate 3 parallel builds that should be the same as your current checkout # They will be placed in the parent directory ('..') as 'AnkiDroid-.parallel..apk' @@ -18,13 +17,7 @@ if [ "$TAG" == "" ]; then exit 1 fi -# Read the key passwords -if [ "$KSTOREPWD" == "" ]; then - read -sp "Enter keystore password: " KSTOREPWD; echo - read -sp "Enter key password: " KEYPWD; echo - export KSTOREPWD - export KEYPWD -fi +. tools/check-keystore.sh # Get on to the tag requested #git checkout $TAG diff --git a/tools/release.sh b/tools/release.sh index 1016cccb8f5e..184fc1ab1657 100755 --- a/tools/release.sh +++ b/tools/release.sh @@ -100,13 +100,7 @@ git add $GRADLEFILE $CHANGELOG git commit -m "Bumped version to $VERSION" git tag v"$VERSION" -# Read the key passwords if needed -if [ "$KSTOREPWD" == "" ]; then - read -rsp "Enter keystore password: " KSTOREPWD; echo - read -rsp "Enter key password: " KEYPWD; echo - export KSTOREPWD - export KEYPWD -fi +. tools/check-keystore.sh # Build signed APK using Gradle and publish to Play. # Do this before building universal of the play flavor so the universal is not uploaded to Play Store From cf1b98d0a22636310092d0d8168272e2721dc344 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Sun, 23 Jun 2024 22:39:19 -0500 Subject: [PATCH 133/138] refactor(test): shift common testlib items into a 'common' package this means they have their own separate directory with no collisions in other modules that consume them --- .../androidTest/java/com/ichi2/anki/NoteEditorIntentTest.kt | 4 ++-- .../java/com/ichi2/anki/tests/ContentProviderTest.kt | 2 +- .../androidTest/java/com/ichi2/anki/tests/InstrumentedTest.kt | 2 +- .../test/java/com/ichi2/anki/AbstractFlashcardViewerTest.kt | 4 ++-- AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt | 4 ++-- AnkiDroid/src/test/java/com/ichi2/anki/ReviewerNoParamTest.kt | 4 ++-- AnkiDroid/src/test/java/com/ichi2/anki/ReviewerTest.kt | 4 ++-- AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt | 2 ++ .../test/java/com/ichi2/anki/dialogs/tags/TagsDialogTest.kt | 4 ++-- .../com/ichi2/anki/servicelayer/scopedstorage/ExecutorTest.kt | 4 ++-- .../main/java/com/ichi2/testutils/{ => common}/AnkiAssert.kt | 2 +- .../testutils/{ => common}/FailOnUnhandledExceptionRule.kt | 2 +- .../ichi2/testutils/{ => common}/IgnoreFlakyTestsInCIRule.kt | 2 +- 13 files changed, 21 insertions(+), 19 deletions(-) rename testlib/src/main/java/com/ichi2/testutils/{ => common}/AnkiAssert.kt (97%) rename testlib/src/main/java/com/ichi2/testutils/{ => common}/FailOnUnhandledExceptionRule.kt (98%) rename testlib/src/main/java/com/ichi2/testutils/{ => common}/IgnoreFlakyTestsInCIRule.kt (99%) diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/NoteEditorIntentTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/NoteEditorIntentTest.kt index 5ec743711713..beb68a081af4 100644 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/NoteEditorIntentTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/NoteEditorIntentTest.kt @@ -24,8 +24,8 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import com.ichi2.anki.NoteEditor.Companion.intentLaunchedWithImage import com.ichi2.anki.tests.InstrumentedTest import com.ichi2.anki.testutil.GrantStoragePermission -import com.ichi2.testutils.Flaky -import com.ichi2.testutils.OS +import com.ichi2.testutils.common.Flaky +import com.ichi2.testutils.common.OS import com.ichi2.utils.AssetHelper.TEXT_PLAIN import junit.framework.TestCase.assertFalse import org.hamcrest.MatcherAssert diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/ContentProviderTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/ContentProviderTest.kt index ad761172932a..d99182720d45 100644 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/ContentProviderTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/ContentProviderTest.kt @@ -33,7 +33,7 @@ import com.ichi2.anki.testutil.grantPermissions import com.ichi2.libanki.* import com.ichi2.libanki.exception.ConfirmModSchemaException import com.ichi2.libanki.sched.Scheduler -import com.ichi2.testutils.assertThrows +import com.ichi2.testutils.common.assertThrows import com.ichi2.utils.KotlinCleanup import com.ichi2.utils.emptyStringArray import net.ankiweb.rsdroid.exceptions.BackendNotFoundException diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/InstrumentedTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/InstrumentedTest.kt index ae38fbb72981..3f6060a496f6 100644 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/InstrumentedTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/InstrumentedTest.kt @@ -32,7 +32,7 @@ import com.ichi2.libanki.Collection import com.ichi2.libanki.Consts import com.ichi2.libanki.Note import com.ichi2.libanki.utils.TimeManager -import com.ichi2.testutils.IgnoreFlakyTestsInCIRule +import com.ichi2.testutils.common.IgnoreFlakyTestsInCIRule import kotlinx.coroutines.runBlocking import net.ankiweb.rsdroid.BackendException import org.junit.After diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/AbstractFlashcardViewerTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/AbstractFlashcardViewerTest.kt index 9140c104bc4e..563c2e7ef960 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/AbstractFlashcardViewerTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/AbstractFlashcardViewerTest.kt @@ -34,8 +34,8 @@ import com.ichi2.anki.servicelayer.LanguageHintService import com.ichi2.libanki.StdModels import com.ichi2.libanki.undoableOp import com.ichi2.testutils.AnkiAssert.assertDoesNotThrow -import com.ichi2.testutils.Flaky -import com.ichi2.testutils.OS +import com.ichi2.testutils.common.Flaky +import com.ichi2.testutils.common.OS import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.* import org.junit.Assert.* diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt index cc5e58fc95e9..f88be9f6aeeb 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt @@ -55,10 +55,10 @@ import com.ichi2.libanki.utils.TimeManager import com.ichi2.testutils.AnkiActivityUtils.getDialogFragment import com.ichi2.testutils.AnkiAssert.assertDoesNotThrow import com.ichi2.testutils.AnkiAssert.assertDoesNotThrowSuspend -import com.ichi2.testutils.Flaky import com.ichi2.testutils.IntentAssert -import com.ichi2.testutils.OS import com.ichi2.testutils.TestClass +import com.ichi2.testutils.common.Flaky +import com.ichi2.testutils.common.OS import com.ichi2.testutils.getSharedPrefs import com.ichi2.ui.FixedTextView import com.ichi2.utils.LanguageUtil diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerNoParamTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerNoParamTest.kt index ed49a6126d57..445a2604489a 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerNoParamTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerNoParamTest.kt @@ -35,8 +35,8 @@ import com.ichi2.anki.reviewer.MappableBinding import com.ichi2.anki.reviewer.MappableBinding.Screen import com.ichi2.libanki.Consts import com.ichi2.libanki.DeckId -import com.ichi2.testutils.Flaky -import com.ichi2.testutils.OS +import com.ichi2.testutils.common.Flaky +import com.ichi2.testutils.common.OS import com.ichi2.themes.Theme import com.ichi2.themes.Themes.currentTheme import org.hamcrest.MatcherAssert.assertThat diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerTest.kt index 9a5370360ab4..5887bc7ee5e8 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerTest.kt @@ -43,9 +43,9 @@ import com.ichi2.libanki.Notetypes import com.ichi2.libanki.exception.ConfirmModSchemaException import com.ichi2.libanki.undoableOp import com.ichi2.libanki.utils.TimeManager -import com.ichi2.testutils.Flaky import com.ichi2.testutils.MockTime -import com.ichi2.testutils.OS +import com.ichi2.testutils.common.Flaky +import com.ichi2.testutils.common.OS import com.ichi2.utils.KotlinCleanup import com.ichi2.utils.deepClone import junit.framework.TestCase.assertEquals diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt index 062c64a36d41..ed08b2f7a322 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt @@ -44,6 +44,8 @@ import com.ichi2.libanki.* import com.ichi2.libanki.Collection import com.ichi2.libanki.utils.TimeManager import com.ichi2.testutils.* +import com.ichi2.testutils.common.FailOnUnhandledExceptionRule +import com.ichi2.testutils.common.IgnoreFlakyTestsInCIRule import com.ichi2.utils.InMemorySQLiteOpenHelperFactory import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/tags/TagsDialogTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/tags/TagsDialogTest.kt index 2d6f8a3c651b..da6044763537 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/tags/TagsDialogTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/tags/TagsDialogTest.kt @@ -33,11 +33,11 @@ import com.ichi2.anki.RobolectricTest import com.ichi2.anki.dialogs.utils.AnKingTags import com.ichi2.anki.model.CardStateFilter import com.ichi2.compat.CompatHelper.Companion.getSerializableCompat -import com.ichi2.testutils.Flaky import com.ichi2.testutils.HamcrestUtils.containsInAnyOrder -import com.ichi2.testutils.OS import com.ichi2.testutils.ParametersUtils import com.ichi2.testutils.RecyclerViewUtils +import com.ichi2.testutils.common.Flaky +import com.ichi2.testutils.common.OS import com.ichi2.ui.CheckBoxTriStates import com.ichi2.utils.ListUtil import org.hamcrest.MatcherAssert.assertThat diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/servicelayer/scopedstorage/ExecutorTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/servicelayer/scopedstorage/ExecutorTest.kt index 708823d458cc..541a8504525e 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/servicelayer/scopedstorage/ExecutorTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/servicelayer/scopedstorage/ExecutorTest.kt @@ -19,8 +19,8 @@ package com.ichi2.anki.servicelayer.scopedstorage import com.ichi2.anki.servicelayer.scopedstorage.migrateuserdata.MigrateUserData.* import com.ichi2.anki.servicelayer.scopedstorage.migrateuserdata.MigrateUserData.Executor import com.ichi2.anki.servicelayer.scopedstorage.migrateuserdata.MigrateUserData.Operation -import com.ichi2.testutils.Flaky -import com.ichi2.testutils.OS +import com.ichi2.testutils.common.Flaky +import com.ichi2.testutils.common.OS import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.equalTo import org.hamcrest.Matchers.hasSize diff --git a/testlib/src/main/java/com/ichi2/testutils/AnkiAssert.kt b/testlib/src/main/java/com/ichi2/testutils/common/AnkiAssert.kt similarity index 97% rename from testlib/src/main/java/com/ichi2/testutils/AnkiAssert.kt rename to testlib/src/main/java/com/ichi2/testutils/common/AnkiAssert.kt index 041d34ad7b40..cd7518da96ac 100644 --- a/testlib/src/main/java/com/ichi2/testutils/AnkiAssert.kt +++ b/testlib/src/main/java/com/ichi2/testutils/common/AnkiAssert.kt @@ -14,7 +14,7 @@ * this program. If not, see . */ -package com.ichi2.testutils +package com.ichi2.testutils.common import org.junit.function.ThrowingRunnable diff --git a/testlib/src/main/java/com/ichi2/testutils/FailOnUnhandledExceptionRule.kt b/testlib/src/main/java/com/ichi2/testutils/common/FailOnUnhandledExceptionRule.kt similarity index 98% rename from testlib/src/main/java/com/ichi2/testutils/FailOnUnhandledExceptionRule.kt rename to testlib/src/main/java/com/ichi2/testutils/common/FailOnUnhandledExceptionRule.kt index 75180e8fd357..552b033c744f 100644 --- a/testlib/src/main/java/com/ichi2/testutils/FailOnUnhandledExceptionRule.kt +++ b/testlib/src/main/java/com/ichi2/testutils/common/FailOnUnhandledExceptionRule.kt @@ -14,7 +14,7 @@ * this program. If not, see . */ -package com.ichi2.testutils +package com.ichi2.testutils.common import org.junit.rules.TestRule import org.junit.runner.Description diff --git a/testlib/src/main/java/com/ichi2/testutils/IgnoreFlakyTestsInCIRule.kt b/testlib/src/main/java/com/ichi2/testutils/common/IgnoreFlakyTestsInCIRule.kt similarity index 99% rename from testlib/src/main/java/com/ichi2/testutils/IgnoreFlakyTestsInCIRule.kt rename to testlib/src/main/java/com/ichi2/testutils/common/IgnoreFlakyTestsInCIRule.kt index 66005f2beedb..02acef9f101c 100644 --- a/testlib/src/main/java/com/ichi2/testutils/IgnoreFlakyTestsInCIRule.kt +++ b/testlib/src/main/java/com/ichi2/testutils/common/IgnoreFlakyTestsInCIRule.kt @@ -14,7 +14,7 @@ * this program. If not, see . */ -package com.ichi2.testutils +package com.ichi2.testutils.common import com.ichi2.anki.BuildConfig import org.hamcrest.CoreMatchers.not From 850c391d4325dbe682b7a6b28215a9f80b86afa7 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Sun, 23 Jun 2024 23:38:36 -0500 Subject: [PATCH 134/138] test: copy testlib common files into androidTest directly we are unable to depend on them in androidTestImplementation terms because android gradle plugin has a bug that breaks coverage with a shared test/androidTest dep we want the code to be truly shared though and just need to work around the issue temporarily (we hope) so a build-time copy seems the least-worst alternative --- AnkiDroid/build.gradle | 14 +++++++++++++- .../java/com/ichi2/testutils/common/.gitignore | 5 +++++ .../ichi2/testutils/common/DO_NOT_EDIT_HERE.txt | 14 ++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 AnkiDroid/src/androidTest/java/com/ichi2/testutils/common/.gitignore create mode 100644 AnkiDroid/src/androidTest/java/com/ichi2/testutils/common/DO_NOT_EDIT_HERE.txt diff --git a/AnkiDroid/build.gradle b/AnkiDroid/build.gradle index 114b4513f345..31116fef17e6 100644 --- a/AnkiDroid/build.gradle +++ b/AnkiDroid/build.gradle @@ -264,6 +264,16 @@ tasks.register('installGitHook', Copy) { // to run manually: `./gradlew installGitHook` tasks.named('preBuild').configure { dependsOn('installGitHook') } +tasks.register('copyTestLibIntoAndroidTest', Copy) { + into new File(rootProject.rootDir, 'AnkiDroid/src/androidTest/java/com/ichi2/testutils') + from new File(rootProject.rootDir, 'testlib/src/main/java/com/ichi2/testutils') + into ('common') { + from 'common' + } +} +tasks.named('preBuild').configure { dependsOn('copyTestLibIntoAndroidTest') } +tasks.named('runKtlintCheckOverAndroidTestSourceSet').configure { mustRunAfter('copyTestLibIntoAndroidTest') } + // Issue 11078 - some emulators run, but run zero tests, and still report success tasks.register('assertNonzeroAndroidTests') { doLast { @@ -408,7 +418,9 @@ dependencies { // for testing flows testImplementation libs.cashapp.turbine - androidTestImplementation project(':testlib') + // we should depend directly on the common testlib for androidTest, but we cannot + // until coverage-breaking issue is fixed https://issuetracker.google.com/issues/332746900 + // androidTestImplementation project(':testlib') // May need a resolution strategy for support libs to our versions androidTestImplementation libs.androidx.espresso.core diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/testutils/common/.gitignore b/AnkiDroid/src/androidTest/java/com/ichi2/testutils/common/.gitignore new file mode 100644 index 000000000000..30ee6415e6d6 --- /dev/null +++ b/AnkiDroid/src/androidTest/java/com/ichi2/testutils/common/.gitignore @@ -0,0 +1,5 @@ +# The files in this directory are copied from testlib dynamically during build +# Copy used instead of `androidTestImplementation(':testlib')` until android gradle plugin +# issue that breaks coverage for shared test/androidTest deps is fixed +# see https://issuetracker.google.com/issues/332746900#comment2 +*.kt \ No newline at end of file diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/testutils/common/DO_NOT_EDIT_HERE.txt b/AnkiDroid/src/androidTest/java/com/ichi2/testutils/common/DO_NOT_EDIT_HERE.txt new file mode 100644 index 000000000000..0adaac33bfcb --- /dev/null +++ b/AnkiDroid/src/androidTest/java/com/ichi2/testutils/common/DO_NOT_EDIT_HERE.txt @@ -0,0 +1,14 @@ +DO NOT EDIT FILES IN THIS DIRECTORY + +FILES IN THIS DIRECTORY ARE AUTO-COPIED BY GRADLE AT BUILD TIME + +If you want to edit the files here, instead: + +1) edit the files in testlib/src/java/com/ichi2/testutils/common +2) run `./gradlew copyTestLibIntoAndroidTest` or a general build + +Then your edits in testlib should be copied here for use in androidTest + +That gradle task, and this entire directory should be removed when +issue https://issuetracker.google.com/issues/332746900 is fixed + From b15994cad0bb4fbd7836bf21be80e24499f67c0a Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Sun, 23 Jun 2024 23:44:53 -0500 Subject: [PATCH 135/138] test: ensure non-zero coverage for androidTest reports there are many toolchain incompatibilities which can result in a false-positive androidTest test run, but with zero actual coverage tallied this adds a finalization task that scans the coverage report looking for an aggregate coverage count that is non-zero --- AnkiDroid/jacoco.gradle | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/AnkiDroid/jacoco.gradle b/AnkiDroid/jacoco.gradle index bab464303fd2..5a866ebe0e84 100644 --- a/AnkiDroid/jacoco.gradle +++ b/AnkiDroid/jacoco.gradle @@ -1,4 +1,5 @@ import groovy.transform.Memoized +import groovy.xml.XmlParser apply plugin: 'jacoco' @@ -167,3 +168,39 @@ def androidTestReport = tasks.register('jacocoAndroidTestReport', JacocoReport) ]) } androidTestReport.configure { dependsOn('connectedPlayDebugAndroidTest') } + +// Issue 16640 - some emulators run, but register zero coverage +tasks.register('assertNonzeroAndroidTestCoverage') { + doLast { + File jacocoReport = layout.buildDirectory.dir("reports/jacoco/jacocoAndroidTestReport/jacocoAndroidTestReport.xml").get().asFile + + if (!jacocoReport.exists()) + throw new FileNotFoundException("jacocoAndroidTestReport.xml was not found after running jacocoAndroidTestReport") + + XmlParser xmlParser = new XmlParser() + xmlParser.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false) + xmlParser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false) + + Node reportRoot = xmlParser.parse(jacocoReport) + boolean hasCovered = false + + // https://github.com/jacoco/jacoco/blob/5aabb2eb60bbcd05df968005f1746ba19dcd5361/org.jacoco.report/src/org/jacoco/report/internal/xml/ReportElement.java#L190 + for (Node child : reportRoot.children()) { + if (child.name() != "counter") + continue; + + if (child.attribute("covered") == "0") { + logger.warn("jacoco registered zero code coverage for counter type %s", child.attribute("type")) + } else { + hasCovered = true + } + } + + if (!hasCovered) + throw new GradleScriptException("androidTest registered zero code coverage in jacocoAndroidTestReport.xml. Probably some incompatibilities in the toolchain.", null) + } +} +afterEvaluate { + tasks.named('jacocoAndroidTestReport').configure { finalizedBy('assertNonzeroAndroidTestCoverage') } + tasks.named('jacocoTestReport').configure { finalizedBy('assertNonzeroAndroidTestCoverage') } +} From b6c1fd314e15f24952cfa520d5523cef1f802397 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Mon, 24 Jun 2024 09:58:12 -0500 Subject: [PATCH 136/138] test: fixup warning message when no coverage of type is found doesn't look like string format works in logger.warn, use concat --- AnkiDroid/jacoco.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AnkiDroid/jacoco.gradle b/AnkiDroid/jacoco.gradle index 5a866ebe0e84..a734025c3868 100644 --- a/AnkiDroid/jacoco.gradle +++ b/AnkiDroid/jacoco.gradle @@ -190,7 +190,7 @@ tasks.register('assertNonzeroAndroidTestCoverage') { continue; if (child.attribute("covered") == "0") { - logger.warn("jacoco registered zero code coverage for counter type %s", child.attribute("type")) + logger.warn("jacoco registered zero code coverage for counter type " + child.attribute("type"), null) } else { hasCovered = true } From bef936d1182691d8934244d12888e76987d3f96a Mon Sep 17 00:00:00 2001 From: Voczi Date: Tue, 25 Jun 2024 13:46:33 +0200 Subject: [PATCH 137/138] Fix publish workflow after recent changes --- .github/workflows/publish.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 75bb4acda34d..dcd3d056899c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -53,17 +53,17 @@ jobs: - name: Credential Prep run: | - export KEYSTOREPATH=$HOME/src/android-keystore - echo "KEYSTOREPATH=$KEYSTOREPATH" >> $GITHUB_ENV + echo "KEYSTOREPATH=$HOME/src/android-keystore" >> $GITHUB_ENV echo "KEYALIAS=nrkeystorealias" >> $GITHUB_ENV echo "KEYSTOREPWD=${{ secrets.KEYSTORE_PASSWORD }}" >> $GITHUB_ENV echo "KEYPWD=${{ secrets.KEYSTORE_KEY_PASSWORD }}" >> $GITHUB_ENV mkdir ~/src - echo "${{ secrets.AMAZON_PUBLISH_CREDENTIALS }}" | base64 -d > ~/src/AnkiDroid-Amazon-Publish-Security-Profile.json.gz - echo "${{ secrets.GOOGLE_PUBLISH_CREDENTIALS }}" | base64 -d > ~/src/AnkiDroid-GCP-Publish-Credentials.json.gz - echo "${{ secrets.RELEASES_PUBLISH_TOKEN }}" | base64 -d > ~/src/my-github-personal-access-token.gz - echo "${{ secrets.KEYSTORE }}" | base64 -d > $KEYSTOREPATH.gz - gunzip $KEYSTOREPATH.gz + cd ~/src + echo "${{ secrets.AMAZON_PUBLISH_CREDENTIALS }}" | base64 -d > ./AnkiDroid-Amazon-Publish-Security-Profile.json.gz + echo "${{ secrets.GOOGLE_PUBLISH_CREDENTIALS }}" | base64 -d > ./AnkiDroid-GCP-Publish-Credentials.json.gz + echo "${{ secrets.RELEASES_PUBLISH_TOKEN }}" | base64 -d > ./my-github-personal-access-token.gz + echo "${{ secrets.KEYSTORE }}" | base64 -d > ./android-keystore.gz + gunzip *.gz shell: bash - name: Build and Release public release From 4aecb2a246a36d2efea0fdb555a2c484d2a884c1 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Tue, 25 Jun 2024 12:09:20 +0000 Subject: [PATCH 138/138] Bumped version to 2.19alpha7 --- AnkiDroid/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AnkiDroid/build.gradle b/AnkiDroid/build.gradle index 31116fef17e6..4009a07467d4 100644 --- a/AnkiDroid/build.gradle +++ b/AnkiDroid/build.gradle @@ -74,8 +74,8 @@ android { // // This ensures the correct ordering between the various types of releases (dev < alpha < beta < release) which is // needed for upgrades to be offered correctly. - versionCode=21900106 - versionName="2.19alpha6" + versionCode=21900107 + versionName="2.19alpha7" minSdk libs.versions.minSdk.get().toInteger() // After #13695: change .tests_emulator.yml targetSdk libs.versions.targetSdk.get().toInteger()