Skip to content

Commit

Permalink
feat: congrats page form Anki Desktop
Browse files Browse the repository at this point in the history
  • Loading branch information
BrayanDSO committed Dec 9, 2023
1 parent 2302779 commit badc84d
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import com.ichi2.anki.dialogs.tags.TagsDialog
import com.ichi2.anki.dialogs.tags.TagsDialogFactory
import com.ichi2.anki.dialogs.tags.TagsDialogListener
import com.ichi2.anki.model.CardStateFilter
import com.ichi2.anki.pages.CongratsPage
import com.ichi2.anki.preferences.sharedPrefs
import com.ichi2.anki.receiver.SdCardReceiver
import com.ichi2.anki.reviewer.*
Expand Down Expand Up @@ -508,7 +509,7 @@ abstract class AbstractFlashcardViewer :
closeReviewer(RESULT_NO_MORE_CARDS)
// When launched with a shortcut, we want to display a message when finishing
if (intent.getBooleanExtra(EXTRA_STARTED_WITH_SHORTCUT, false)) {
showThemedToast(baseContext, R.string.studyoptions_congrats_finished, false)
startActivity(CongratsPage.getIntent(this))
}
return
}
Expand Down
54 changes: 6 additions & 48 deletions AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ import com.ichi2.anki.dialogs.ImportFileSelectionFragment.CsvImportResultLaunche
import com.ichi2.anki.dialogs.MediaCheckDialog.MediaCheckDialogListener
import com.ichi2.anki.dialogs.SyncErrorDialog.Companion.newInstance
import com.ichi2.anki.dialogs.SyncErrorDialog.SyncErrorDialogListener
import com.ichi2.anki.dialogs.customstudy.CustomStudyDialog
import com.ichi2.anki.dialogs.customstudy.CustomStudyDialog.CustomStudyListener
import com.ichi2.anki.dialogs.customstudy.CustomStudyDialogFactory
import com.ichi2.anki.export.ActivityExportingDelegate
import com.ichi2.anki.export.ExportType
import com.ichi2.anki.notetype.ManageNotetypes
import com.ichi2.anki.pages.AnkiPackageImporterFragment
import com.ichi2.anki.pages.CongratsPage
import com.ichi2.anki.preferences.AdvancedSettingsFragment
import com.ichi2.anki.preferences.sharedPrefs
import com.ichi2.anki.receiver.SdCardReceiver
Expand Down Expand Up @@ -966,12 +966,7 @@ open class DeckPicker :

private fun processReviewResults(resultCode: Int) {
if (resultCode == AbstractFlashcardViewer.RESULT_NO_MORE_CARDS) {
// Show a message when reviewing has finished
if (getColUnsafe.sched.totalCount() == 0) {
showSnackbar(R.string.studyoptions_congrats_finished)
} else {
showSnackbar(R.string.studyoptions_no_cards_due)
}
startActivity(CongratsPage.getIntent(this))
} else if (resultCode == AbstractFlashcardViewer.RESULT_ABORT_AND_SYNC) {
Timber.i("Obtained Abort and Sync result")
sync()
Expand Down Expand Up @@ -1720,36 +1715,11 @@ open class DeckPicker :

@NeedsTest("14608: Ensure that the deck options refer to the selected deck")
private suspend fun handleDeckSelection(did: DeckId, selectionType: DeckSelectionType) {
fun showStudyMoreSnackbar(did: DeckId) =
showSnackbar(R.string.studyoptions_limit_reached) {
addCallback(mSnackbarShowHideCallback)
setAction(R.string.study_more) {
val d = mCustomStudyDialogFactory.newCustomStudyDialog().withArguments(
CustomStudyDialog.ContextMenuConfiguration.LIMITS,
did,
true
)
showDialogFragment(d)
}
}

fun showEmptyDeckSnackbar() = showSnackbar(R.string.empty_deck) {
addCallback(mSnackbarShowHideCallback)
setAction(R.string.menu_add) { addNote() }
}

fun showCustomStudySnackbar() = showSnackbar(R.string.studyoptions_empty_schedule) {
addCallback(mSnackbarShowHideCallback)
setAction(R.string.custom_study) {
val d = mCustomStudyDialogFactory.newCustomStudyDialog().withArguments(
CustomStudyDialog.ContextMenuConfiguration.EMPTY_SCHEDULE,
did,
true
)
showDialogFragment(d)
}
}

/** Check if we need to update the fragment or update the deck list */
fun updateUi() {
if (fragmented) {
Expand Down Expand Up @@ -1779,29 +1749,17 @@ open class DeckPicker :
}

when (queryCompletedDeckCustomStudyAction(did)) {
CompletedDeckStatus.LEARN_AHEAD_LIMIT_REACHED -> {
// If there are cards due that can't be studied yet (due to the learn ahead limit) then go to study options
openStudyOptions(withDeckOptions = false)
}
CompletedDeckStatus.LEARN_AHEAD_LIMIT_REACHED,
CompletedDeckStatus.REGULAR_DECK_NO_MORE_CARDS_TODAY,
CompletedDeckStatus.DYNAMIC_DECK_NO_LIMITS_REACHED,
CompletedDeckStatus.DAILY_STUDY_LIMIT_REACHED -> {
// If there are no cards to review because of the daily study limit then give "Study more" option
showStudyMoreSnackbar(did)
updateUi()
}
CompletedDeckStatus.DYNAMIC_DECK_NO_LIMITS_REACHED -> {
// Go to the study options screen if filtered deck with no cards to study
openStudyOptions(withDeckOptions = false)
startActivity(CongratsPage.getIntent(this))
}
CompletedDeckStatus.EMPTY_REGULAR_DECK -> {
// If the deck is empty (& has no children) then show a message saying it's empty
showEmptyDeckSnackbar()
updateUi()
}
CompletedDeckStatus.REGULAR_DECK_NO_MORE_CARDS_TODAY -> {
// Otherwise say there are no cards scheduled to study, and give option to do custom study
showCustomStudySnackbar()
updateUi()
}
}
}

Expand Down
1 change: 1 addition & 0 deletions AnkiDroid/src/main/java/com/ichi2/anki/pages/AnkiServer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ open class AnkiServer(
"setWantsAbort" -> CollectionManager.getBackend().setWantsAbortRaw(bytes)
"evaluateWeights" -> withCol { evaluateWeightsRaw(bytes) }
"latestProgress" -> CollectionManager.getBackend().latestProgressRaw(bytes)
"congratsInfo" -> withCol { congratsInfoRaw(bytes) }
else -> { throw Exception("unhandled request: $methodName") }
}
}
Expand Down
32 changes: 32 additions & 0 deletions AnkiDroid/src/main/java/com/ichi2/anki/pages/CongratsPage.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2023 Brayan Oliveira <brayandso.dev@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.ichi2.anki.pages

import android.content.Context
import android.content.Intent

class CongratsPage : PageFragment() {
override val title: Int? = null
override val pageName = "congrats"
override var webViewClient: PageWebViewClient = PageWebViewClient()
override var webChromeClient: PageChromeClient = PageChromeClient()

companion object {
fun getIntent(context: Context): Intent {
return PagesActivity.getIntent(context, CongratsPage::class)
}
}
}
13 changes: 13 additions & 0 deletions AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import anki.card_rendering.EmptyCardsReport
import anki.collection.OpChanges
import anki.collection.OpChangesWithCount
import anki.config.ConfigKey
import anki.scheduler.CongratsInfoResponse
import anki.search.SearchNode
import anki.sync.SyncAuth
import anki.sync.SyncStatusResponse
Expand Down Expand Up @@ -715,4 +716,16 @@ open class Collection(
return backend.clozeNumbersInNote(n.toBackendNote())
.sorted()
}

// TODO either support bridgeCommand here
// or replace it with POST requests in Anki Desktop (preferable)
// https://github.com/ankidroid/Anki-Android/issues/14361#issuecomment-1701946364
fun congratsInfoRaw(input: ByteArray): ByteArray {
val byteArray = backend.congratsInfoRaw(input = input)
val response = CongratsInfoResponse.parseFrom(byteArray)
return CongratsInfoResponse.newBuilder(response)
.setBridgeCommandsSupported(false)
.build()
.toByteArray()
}
}
3 changes: 0 additions & 3 deletions AnkiDroid/src/main/res/values/01-core.xml
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,6 @@
<string name="search_for_download_deck" comment="Deck search value for downloading deck">Deck Search</string>
<string name="invalid_deck_name">Invalid deck name</string>
<string name="studyoptions_empty">This deck is empty. Press the + button to add new content.</string>
<string name="studyoptions_limit_reached">Daily study limit reached</string>
<string name="studyoptions_empty_schedule">No cards scheduled to study</string>
<string name="studyoptions_congrats_finished">Congratulations! You have finished for now.</string>
<string name="studyoptions_no_cards_due">No cards are due yet</string>

<string name="sd_card_not_mounted">Device storage not mounted</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import org.mockito.Mockito.*
import org.robolectric.Robolectric
import org.robolectric.Shadows
import org.robolectric.android.controller.ActivityController
import org.robolectric.shadows.ShadowToast
import java.util.*
import java.util.stream.Stream
import com.ichi2.anim.ActivityTransitionAnimation.Direction as Direction
Expand Down Expand Up @@ -252,14 +251,6 @@ class AbstractFlashcardViewerTest : RobolectricTest() {
assertThat("no auto answer after onRenderProcessGone when paused", viewer.hasAutomaticAnswerQueued(), equalTo(false))
}

@Test
fun shortcutShowsToastOnFinish() = runTest {
val viewer: NonAbstractFlashcardViewer = getViewer(true, true)
viewer.executeCommand(ViewerCommand.FLIP_OR_ANSWER_EASE4)
viewer.executeCommand(ViewerCommand.FLIP_OR_ANSWER_EASE4)
assertEquals(getResourceString(R.string.studyoptions_congrats_finished), ShadowToast.getTextOfLatestToast())
}

@Test
fun `Show audio play buttons preference handling - sound`() = runTest {
addNoteUsingBasicTypedModel("SOUND [sound:android_audiorec.3gp]", "back")
Expand Down

0 comments on commit badc84d

Please sign in to comment.