Skip to content

Commit bb4e0a5

Browse files
authored
Merge branch 'ankidroid:main' into main
2 parents f86badd + a71b31d commit bb4e0a5

15 files changed

Lines changed: 83 additions & 318 deletions

File tree

AnkiDroid/src/androidTest/java/com/ichi2/anki/testutil/MockReviewerUi.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import com.ichi2.anki.reviewer.ReviewerUi.ControlBlock
2121
class MockReviewerUi : ReviewerUi {
2222
override var isDisplayingAnswer = false
2323
private set
24+
25+
override fun isActionButton(id: Int): Boolean = throw UnsupportedOperationException()
26+
2427
override val controlBlocked: ControlBlock?
2528
get() = null
2629

AnkiDroid/src/androidTest/java/com/ichi2/ui/ActionBarOverflowTest.kt

Lines changed: 0 additions & 94 deletions
This file was deleted.

AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ import kotlin.math.abs
118118
@KotlinCleanup("lots to deal with")
119119
abstract class AbstractFlashcardViewer :
120120
NavigationDrawerActivity(),
121-
ReviewerUi,
122121
ViewerCommand.CommandProcessor,
123122
TagsDialogListener,
124123
WhiteboardMultiTouchMethods,
@@ -147,7 +146,7 @@ abstract class AbstractFlashcardViewer :
147146
private var mScrollingButtons = false
148147
private var mGesturesEnabled = false
149148
private var mLargeAnswerButtons = false
150-
private var mAnswerButtonsPosition: String? = "bottom"
149+
protected var mAnswerButtonsPosition: String? = "bottom"
151150
private var mDoubleTapTimeInterval = DEFAULT_DOUBLE_TAP_TIME_INTERVAL
152151

153152
// Android WebView
@@ -242,7 +241,7 @@ abstract class AbstractFlashcardViewer :
242241
private val mCardLock: ReadWriteLock = ReentrantReadWriteLock()
243242

244243
/** whether controls are currently blocked, and how long we expect them to be */
245-
override var controlBlocked = ControlBlock.SLOW
244+
open var controlBlocked = ControlBlock.SLOW
246245

247246
/** Preference: Whether the user wants press back twice to return to the main screen" */
248247
private var mExitViaDoubleTapBack = false
@@ -2538,10 +2537,10 @@ abstract class AbstractFlashcardViewer :
25382537
GetCard().runWithHandler(answerCardHandler(false))
25392538
}
25402539

2541-
override val isDisplayingAnswer
2540+
val isDisplayingAnswer
25422541
get() = displayAnswer
25432542

2544-
override val isControlBlocked: Boolean
2543+
open val isControlBlocked: Boolean
25452544
get() = controlBlocked !== ControlBlock.UNBLOCKED
25462545

25472546
@VisibleForTesting(otherwise = VisibleForTesting.NONE)

AnkiDroid/src/main/java/com/ichi2/anki/DeckOptionsActivity.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -558,9 +558,7 @@ class DeckOptionsActivity :
558558
}
559559

560560
// TODO Tracked in https://github.com/ankidroid/Anki-Android/issues/5019
561-
@KotlinCleanup("remove reduntant val res = resources")
562561
override fun updateSummaries() {
563-
val res = resources
564562
// for all text preferences, set summary as current database value
565563
for (key in pref.mValues.keys) {
566564
val pref = findPreference(key)
@@ -569,7 +567,7 @@ class DeckOptionsActivity :
569567
val count = optionsGroupCount
570568
// Escape "%" in groupName as it's treated as a token
571569
groupName = groupName.replace("%".toRegex(), "%%")
572-
pref!!.summary = res.getQuantityString(R.plurals.deck_conf_group_summ, count, groupName, count)
570+
pref!!.summary = resources.getQuantityString(R.plurals.deck_conf_group_summ, count, groupName, count)
573571
continue
574572
}
575573

@@ -596,7 +594,7 @@ class DeckOptionsActivity :
596594
}
597595
// Update summaries of preference items that don't have values (aren't in mValues)
598596
val subDeckCount = subdeckCount
599-
findPreference("confSetSubdecks").summary = res.getQuantityString(R.plurals.deck_conf_set_subdecks_summ, subDeckCount, subDeckCount)
597+
findPreference("confSetSubdecks").summary = resources.getQuantityString(R.plurals.deck_conf_set_subdecks_summ, subDeckCount, subDeckCount)
600598
}
601599

602600
// TODO Tracked in https://github.com/ankidroid/Anki-Android/issues/5019

AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,7 +1689,6 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags
16891689
toolbar.visibility = View.VISIBLE
16901690
}
16911691
toolbar.clearCustomItems()
1692-
val clozeIcon = toolbar.clozeIcon
16931692
if (mEditorNote!!.model().isCloze) {
16941693
val clozeFormatter = Toolbar.TextFormatter { s: String ->
16951694
val stringFormat = Toolbar.StringFormat()
@@ -1704,10 +1703,11 @@ class NoteEditor : AnkiActivity(), DeckSelectionListener, SubtitleListener, Tags
17041703
}
17051704
stringFormat
17061705
}
1707-
clozeIcon!!.setOnClickListener { toolbar.onFormat(clozeFormatter) }
1708-
clozeIcon.visibility = View.VISIBLE
1709-
} else {
1710-
clozeIcon!!.visibility = View.GONE
1706+
1707+
val clozeDrawable = ResourcesCompat.getDrawable(resources, R.drawable.ic_cloze_black_24dp, null)
1708+
clozeDrawable!!.setTint(Themes.getColorFromAttr(this@NoteEditor, R.attr.toolbarIconColor))
1709+
val clozeButton = toolbar.insertItem(0, clozeDrawable, Runnable { toolbar.onFormat(clozeFormatter) })
1710+
clozeButton.contentDescription = resources.getString(R.string.insert_cloze)
17111711
}
17121712
val buttons = toolbarButtons
17131713
for (b in buttons) {

AnkiDroid/src/main/java/com/ichi2/anki/Reviewer.kt

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,11 @@ import com.ichi2.libanki.utils.TimeManager
8282
import com.ichi2.themes.Themes
8383
import com.ichi2.themes.Themes.currentTheme
8484
import com.ichi2.themes.Themes.getColorFromAttr
85+
import com.ichi2.utils.*
8586
import com.ichi2.utils.AndroidUiUtils.isRunningOnTv
86-
import com.ichi2.utils.Computation
8787
import com.ichi2.utils.HandlerUtils.getDefaultLooper
88-
import com.ichi2.utils.KotlinCleanup
8988
import com.ichi2.utils.Permissions.canRecordAudio
9089
import com.ichi2.utils.ViewGroupUtils.setRenderWorkaround
91-
import com.ichi2.utils.iconAlpha
92-
import com.ichi2.utils.increaseHorizontalPaddingOfOverflowMenuIcons
93-
import com.ichi2.utils.tintOverflowMenuIcons
9490
import com.ichi2.widget.WidgetStatus.update
9591
import net.ankiweb.rsdroid.BackendFactory
9692
import timber.log.Timber
@@ -99,7 +95,9 @@ import java.lang.ref.WeakReference
9995
import java.util.function.Consumer
10096

10197
@KotlinCleanup("too many to count")
102-
open class Reviewer : AbstractFlashcardViewer() {
98+
open class Reviewer :
99+
AbstractFlashcardViewer(),
100+
ReviewerUi {
103101
private var mHasDrawerSwipeConflicts = false
104102
private var mShowWhiteboard = true
105103
private var mPrefFullscreenReview = false
@@ -157,6 +155,8 @@ open class Reviewer : AbstractFlashcardViewer() {
157155
}
158156
}
159157

158+
override fun isActionButton(id: Int): Boolean = mToolbar.isActionButton(id)
159+
160160
override fun onCreate(savedInstanceState: Bundle?) {
161161
if (showedActivityFailedScreen(savedInstanceState)) {
162162
return
@@ -201,7 +201,7 @@ open class Reviewer : AbstractFlashcardViewer() {
201201
return CardMarker.FLAG_NONE
202202
}
203203
val isShownInActionBar = mActionButtons.isShownInActionBar(ActionButtons.RES_FLAG)
204-
return if (isShownInActionBar != null && isShownInActionBar && !mPrefFullscreenReview) {
204+
return if (isShownInActionBar && !mPrefFullscreenReview) {
205205
CardMarker.FLAG_NONE
206206
} else actualValue
207207
}
@@ -230,7 +230,7 @@ open class Reviewer : AbstractFlashcardViewer() {
230230
val isShownInActionBar = mActionButtons.isShownInActionBar(ActionButtons.RES_MARK)
231231
// If we don't know, show it.
232232
// Otherwise, if it's in the action bar, don't show it again.
233-
return isShownInActionBar == null || !isShownInActionBar || mPrefFullscreenReview
233+
return !isShownInActionBar || mPrefFullscreenReview
234234
}
235235

236236
protected open fun onMark(card: Card?) {
@@ -436,6 +436,7 @@ open class Reviewer : AbstractFlashcardViewer() {
436436
} else {
437437
mColorPalette!!.visibility = View.GONE
438438
}
439+
updateWhiteboardEditorPosition()
439440
}
440441
R.id.action_save_whiteboard -> {
441442
Timber.i("Reviewer:: Save whiteboard button pressed")
@@ -1042,6 +1043,26 @@ open class Reviewer : AbstractFlashcardViewer() {
10421043
updateScreenCounts()
10431044
}
10441045

1046+
private fun updateWhiteboardEditorPosition() {
1047+
mAnswerButtonsPosition = AnkiDroidApp.getSharedPrefs(this)
1048+
.getString("answerButtonPosition", "bottom")
1049+
val layoutParams: RelativeLayout.LayoutParams
1050+
when (mAnswerButtonsPosition) {
1051+
"none", "top" -> {
1052+
layoutParams = mColorPalette!!.layoutParams as RelativeLayout.LayoutParams
1053+
layoutParams.removeRule(RelativeLayout.ABOVE)
1054+
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
1055+
mColorPalette!!.layoutParams = layoutParams
1056+
}
1057+
"bottom" -> {
1058+
layoutParams = mColorPalette!!.layoutParams as RelativeLayout.LayoutParams
1059+
layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
1060+
layoutParams.addRule(RelativeLayout.ABOVE, R.id.bottom_area_layout)
1061+
mColorPalette!!.layoutParams = layoutParams
1062+
}
1063+
}
1064+
}
1065+
10451066
protected fun updateScreenCounts() {
10461067
if (currentCard == null) return
10471068
super.updateActionBar()

AnkiDroid/src/main/java/com/ichi2/anki/noteeditor/Toolbar.kt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,6 @@ class Toolbar : FrameLayout {
6868
private val mCustomButtons: MutableList<View> = ArrayList()
6969
private val mRows: MutableList<LinearLayout> = ArrayList()
7070

71-
/**
72-
* TODO HACK until API 21 - can be removed once tested.
73-
*
74-
* inside NoteEditor: use [insertItem] instead of accessing this
75-
* and remove [R.id.note_editor_toolbar_button_cloze] from [R.layout.note_editor_toolbar]
76-
*/
77-
var clozeIcon: View? = null
78-
private set
7971
private var mStringPaint: Paint? = null
8072

8173
constructor(context: Context) : super(context)
@@ -92,7 +84,6 @@ class Toolbar : FrameLayout {
9284
}
9385
mToolbar = findViewById(R.id.editor_toolbar_internal)
9486
mToolbarLayout = findViewById(R.id.toolbar_layout)
95-
clozeIcon = findViewById(R.id.note_editor_toolbar_button_cloze)
9687
setupDefaultButtons()
9788
}
9889

AnkiDroid/src/main/java/com/ichi2/anki/reviewer/ActionButtons.kt

Lines changed: 3 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,13 @@ package com.ichi2.anki.reviewer
1717

1818
import android.content.SharedPreferences
1919
import android.view.Menu
20-
import android.view.MenuItem
2120
import androidx.annotation.IdRes
2221
import com.ichi2.anki.R
23-
import com.ichi2.ui.ActionBarOverflow
24-
import timber.log.Timber
2522

26-
class ActionButtons(reviewerUi: ReviewerUi) {
23+
class ActionButtons(private val reviewerUi: ReviewerUi) {
2724
// DEFECT: This should be private - it breaks the law of demeter, but it'll be a large refactoring to get
2825
// to this point
29-
val status: ActionButtonStatus
26+
val status: ActionButtonStatus = ActionButtonStatus(reviewerUi)
3027
private var mMenu: Menu? = null
3128
fun setup(preferences: SharedPreferences) {
3229
status.setup(preferences)
@@ -38,44 +35,7 @@ class ActionButtons(reviewerUi: ReviewerUi) {
3835
mMenu = menu
3936
}
4037

41-
fun isShownInActionBar(@IdRes resId: Int): Boolean? {
42-
val menuItem = findMenuItem(resId) ?: return null
43-
// firstly, see if we can definitively determine whether the action is visible.
44-
val isActionButton = ActionBarOverflow.isActionButton(menuItem)
45-
return isActionButton ?: isLikelyActionButton(resId)
46-
// If not, use heuristics based on preferences.
47-
}
48-
49-
private fun findMenuItem(@IdRes resId: Int): MenuItem? {
50-
return if (mMenu == null) {
51-
null
52-
} else mMenu!!.findItem(resId)
53-
}
54-
55-
private fun isLikelyActionButton(@IdRes resourceId: Int): Boolean {
56-
/*
57-
https://github.com/ankidroid/Anki-Android/pull/5918#issuecomment-609484093
58-
Heuristic approach: Show the item in the top bar unless the corresponding menu item is set to "always" show.
59-
60-
There are two scenarios where the heuristic fails:
61-
62-
1. An item is set to 'if room' but is actually visible in the toolbar
63-
2. An item is set to 'always' but is actually not visible in the toolbar
64-
65-
Failure scenario one is totally acceptable IMO as it just falls back to the current behavior.
66-
Failure scenario two is not ideal, but it should only happen in the pathological case where the user has gone
67-
and explicitly changed the preferences to set more items to 'always' than there is room for in the toolbar.
68-
69-
In any case, both failure scenarios only happen if the user deviated from the default settings in strange ways.
70-
*/
71-
val status = status.getByMenuResourceId(resourceId)
72-
if (status == null) {
73-
Timber.w("Failed to get status for resource: %d", resourceId)
74-
// If we return "true", we may hide the flag/mark status completely. False is safer.
75-
return false
76-
}
77-
return status == ActionButtonStatus.SHOW_AS_ACTION_ALWAYS
78-
}
38+
fun isShownInActionBar(@IdRes id: Int): Boolean = reviewerUi.isActionButton(id)
7939

8040
companion object {
8141
@IdRes
@@ -84,8 +44,4 @@ class ActionButtons(reviewerUi: ReviewerUi) {
8444
@IdRes
8545
val RES_MARK = R.id.action_mark_card
8646
}
87-
88-
init {
89-
status = ActionButtonStatus(reviewerUi)
90-
}
9147
}

AnkiDroid/src/main/java/com/ichi2/anki/reviewer/ReviewerUi.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
package com.ichi2.anki.reviewer
18+
import androidx.annotation.IdRes
1819

1920
interface ReviewerUi {
2021
/** How to block UI buttons. */
@@ -36,4 +37,5 @@ interface ReviewerUi {
3637
val controlBlocked: ControlBlock?
3738
val isControlBlocked: Boolean
3839
val isDisplayingAnswer: Boolean
40+
fun isActionButton(@IdRes id: Int): Boolean
3941
}

0 commit comments

Comments
 (0)