Skip to content

Commit

Permalink
feature: Allow changing deck name in statistics screen
Browse files Browse the repository at this point in the history
  • Loading branch information
criticalAY committed Feb 26, 2024
1 parent f145def commit f996aaf
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 9 deletions.
3 changes: 3 additions & 0 deletions AnkiDroid/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,9 @@
android:exported="false"
android:configChanges="orientation|screenSize"
/>
<activity android:name="com.ichi2.anki.StatisticsActivity"
android:exported="false"
android:configChanges="orientation|screenSize" />
<activity
android:name="com.ichi2.anki.previewer.PreviewerActivity"
android:exported="false"
Expand Down
100 changes: 100 additions & 0 deletions AnkiDroid/src/main/java/com/ichi2/anki/StatisticsActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright (c) 2024 Ashish Yadav <[email protected]>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.ichi2.anki

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.widget.Spinner
import androidx.appcompat.app.ActionBar
import androidx.fragment.app.Fragment
import androidx.lifecycle.MutableLiveData
import com.ichi2.anki.dialogs.DeckSelectionDialog
import com.ichi2.anki.widgets.DeckDropDownAdapter
import com.ichi2.libanki.Collection
import com.ichi2.libanki.DeckId
import kotlin.reflect.KClass
import kotlin.reflect.jvm.jvmName

/**
* Handles changing of deck in Statistics webview
*
* Based in [SingleFragmentActivity], but with `configChanges="orientation|screenSize"`
* to avoid unwanted activity recreations
*/
class StatisticsActivity :
SingleFragmentActivity(),
DeckSelectionDialog.DeckSelectionListener,
DeckDropDownAdapter.SubtitleListener {

override val subtitleText: String
get() = resources.getString(R.string.statistics)

private var deckSpinnerSelection: DeckSpinnerSelection? = null
var deckId: DeckId = 0
var deckNameLive = MutableLiveData<String>()
private var collection: Collection? = null

override fun onCollectionLoaded(col: Collection) {
super.onCollectionLoaded(col)
collection = col
}

// menu wouldn't be visible in fragment's toolbar unless we override here
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.statistics, menu)
return super.onCreateOptionsMenu(menu)
}

fun setupDeckSelector(spinner: Spinner, supportActionBar: ActionBar) {
startLoadingCollection()
deckSpinnerSelection = DeckSpinnerSelection(
this,
spinner,
showAllDecks = true,
alwaysShowDefault = false,
showFilteredDecks = false
).apply {
collection?.let {
initializeActionBarDeckSpinner(it, supportActionBar)
launchCatchingTask { selectDeckById(deckId, true) }
}
}
}

override fun onDeckSelected(deck: DeckSelectionDialog.SelectableDeck?) {
if (deck == null) {
return
}
deckNameLive.value = deck.name
deckId = deck.deckId
launchCatchingTask {
deckSpinnerSelection!!.selectDeckById(deckId, true)
}
}

companion object {

fun getIntent(context: Context, fragmentClass: KClass<out Fragment>, arguments: Bundle? = null): Intent {
return Intent(context, StatisticsActivity::class.java).apply {
putExtra(FRAGMENT_NAME_EXTRA, fragmentClass.jvmName)
putExtra(FRAGMENT_ARGS_EXTRA, arguments)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import timber.log.Timber
*/
@Suppress("LeakingThis")
abstract class PageFragment : Fragment(R.layout.page_fragment), PostRequestHandler {
abstract val title: String
abstract val title: String?
abstract val pageName: String

lateinit var webView: WebView
Expand Down
49 changes: 44 additions & 5 deletions AnkiDroid/src/main/java/com/ichi2/anki/pages/Statistics.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,71 @@ import android.os.Bundle
import android.print.PrintAttributes
import android.print.PrintManager
import android.view.View
import android.widget.Spinner
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat.getSystemService
import androidx.lifecycle.Observer
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.StatisticsActivity
import com.ichi2.anki.utils.getTimestamp
import com.ichi2.libanki.utils.TimeManager
import timber.log.Timber

class Statistics : PageFragment() {
override val title: String
get() = resources.getString(R.string.statistics)
override val title: String?
get() = null

override val pageName = "graphs"

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.findViewById<MaterialToolbar>(R.id.toolbar)?.apply {

val toolbar = view.findViewById<MaterialToolbar>(R.id.toolbar)
(activity as? AppCompatActivity)?.setSupportActionBar(toolbar)

toolbar.apply {
inflateMenu(R.menu.statistics)
menu.findItem(R.id.action_export_stats).title = CollectionManager.TR.statisticsSavePdf()

setOnMenuItemClickListener { item ->
if (item.itemId == R.id.action_export_stats) {
exportWebViewContentAsPDF()
}
true
}
val toolbarSpinner = findViewById<Spinner>(R.id.stats_toolbar_spinner)
toolbarSpinner.visibility = View.VISIBLE
val supportActionBar = (activity as? StatisticsActivity)?.supportActionBar

if (supportActionBar != null) {
(activity as? StatisticsActivity)?.setupDeckSelector(toolbarSpinner, supportActionBar)
} else {
Timber.w("SupportActionBar is null")
}
}

(activity as? StatisticsActivity)?.deckNameLive?.observe(
viewLifecycleOwner,
Observer { deck ->
changeDeck(deck)
}
)
}

/**
* This method is a workaround to change the deck in the webview by finding the text box and
* replacing the deck name with the selected deck name from the dialog and updating the stats
**/
private fun changeDeck(selectedDeck: String) {
val javascriptCode = """
var textBox = [].slice.call(document.getElementsByTagName('input'), 0).filter(x => x.type == "text")[0];
textBox.value = "deck:$selectedDeck";
textBox.dispatchEvent(new Event("input", { bubbles: true }));
textBox.dispatchEvent(new Event("change"));
""".trimIndent()
webView.evaluateJavascript(javascriptCode, null)
}

/**Prepares and initiates a printing task for the content(stats) displayed in the WebView.
Expand All @@ -66,7 +105,7 @@ class Statistics : PageFragment() {

companion object {
fun getIntent(context: Context): Intent {
return SingleFragmentActivity.getIntent(context, Statistics::class)
return StatisticsActivity.getIntent(context, Statistics::class)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.ichi2.anki.R
import com.ichi2.anki.StatisticsActivity
import com.ichi2.libanki.DeckNameId
import com.ichi2.themes.Theme
import com.ichi2.themes.Themes

class DeckDropDownAdapter(private val context: Context, decks: List<DeckNameId>) : BaseAdapter() {
private val deckList = decks.toMutableList()
Expand Down Expand Up @@ -69,6 +73,14 @@ class DeckDropDownAdapter(private val context: Context, decks: List<DeckNameId>)
convertView = LayoutInflater.from(context).inflate(R.layout.dropdown_deck_selected_item, parent, false)
deckNameView = convertView.findViewById(R.id.dropdown_deck_name)
deckCountsView = convertView.findViewById(R.id.dropdown_deck_counts)
// Spinner has white text color in light theme, we change it only for StatisticsActivity
if (context is StatisticsActivity && (Themes.currentTheme.id == Theme.LIGHT.id)) {
deckNameView?.setTextColor(ContextCompat.getColor(context, android.R.color.black))
val drawableEnd = ContextCompat.getDrawable(context, R.drawable.ic_spinner_triangle)
drawableEnd?.setTint(ContextCompat.getColor(context, android.R.color.black))
deckNameView?.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, drawableEnd, null)
deckCountsView?.setTextColor(ContextCompat.getColor(context, android.R.color.black))
}
viewHolder = DeckDropDownViewHolder()
viewHolder.deckNameView = deckNameView
viewHolder.deckCountsView = deckCountsView
Expand Down
17 changes: 14 additions & 3 deletions AnkiDroid/src/main/res/layout/page_fragment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,26 @@
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"

app:layout_constraintTop_toTopOf="parent"
app:navigationContentDescription="@string/abc_action_bar_up_description"
app:navigationIcon="?attr/homeAsUpIndicator"
/>
app:navigationIcon="?attr/homeAsUpIndicator">

<Spinner
android:id="@+id/stats_toolbar_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:background="?attr/selectableItemBackground"
app:popupTheme="@style/ActionBar.Popup" />

</com.google.android.material.appbar.MaterialToolbar>

<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:visibility="invisible"/>

</LinearLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ object ActivityList {
get(PermissionsActivity::class.java),
get(SingleFragmentActivity::class.java),
get(ImageOcclusionActivity::class.java),
get(StatisticsActivity::class.java),
get(PreviewerActivity::class.java)
)
}
Expand Down

0 comments on commit f996aaf

Please sign in to comment.