Skip to content

Commit

Permalink
Note editor toolbar new item string as icon (#10290)
Browse files Browse the repository at this point in the history
* Note editor toolbar new item string as icon

* preferences upgrade with test
  • Loading branch information
krmanik authored Feb 17, 2022
1 parent d9a6620 commit 2bed6c3
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 8 deletions.
12 changes: 9 additions & 3 deletions AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.java
Original file line number Diff line number Diff line change
Expand Up @@ -1914,6 +1914,11 @@ private void updateToolbar() {
// 0th button shows as '1' and is Ctrl + 1
int visualIndex = b.getIndex() + 1;
String text = Integer.toString(visualIndex);

if (!b.getButtonText().isEmpty()) {
text = b.getButtonText();
}

Drawable bmp = mToolbar.createDrawableForString(text);

View v = mToolbar.insertItem(0, bmp, b.toFormatter());
Expand Down Expand Up @@ -1946,14 +1951,14 @@ private void saveToolbarButtons(ArrayList<CustomToolbarButton> buttons) {
.apply();
}

private void addToolbarButton(String prefix, String suffix) {
private void addToolbarButton(String buttonText, String prefix, String suffix) {
if (TextUtils.isEmpty(prefix) && TextUtils.isEmpty(suffix)) {
return;
}

ArrayList<CustomToolbarButton> toolbarButtons = getToolbarButtons();

toolbarButtons.add(new CustomToolbarButton(toolbarButtons.size(), prefix, suffix));
toolbarButtons.add(new CustomToolbarButton(toolbarButtons.size(), buttonText, prefix, suffix));
saveToolbarButtons(toolbarButtons);

updateToolbar();
Expand Down Expand Up @@ -1988,10 +1993,11 @@ private void displayAddToolbarDialog() {
.onNeutral((m, v) -> openUrl(Uri.parse(getString(R.string.link_manual_note_format_toolbar))))
.onPositive((m, v) -> {
View view = m.getView();
EditText etIcon = view.findViewById(R.id.note_editor_toolbar_item_icon);
EditText et = view.findViewById(R.id.note_editor_toolbar_before);
EditText et2 = view.findViewById(R.id.note_editor_toolbar_after);

addToolbarButton(et.getText().toString(), et2.getText().toString());
addToolbarButton(etIcon.getText().toString(), et.getText().toString(), et2.getText().toString());
})
.show();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,21 @@ import com.ichi2.utils.HashUtil.HashSetInit
import timber.log.Timber
import java.util.*

class CustomToolbarButton(var index: Int, private val prefix: String, private val suffix: String) {
typealias ButtonText = String

class CustomToolbarButton(var index: Int, var buttonText: ButtonText, private val prefix: String, private val suffix: String) {
fun toFormatter(): Toolbar.TextFormatter {
return TextWrapper(prefix, suffix)
}

companion object {
private const val KEEP_EMPTY_ENTRIES = -1
const val KEEP_EMPTY_ENTRIES = -1
fun fromString(s: String?): CustomToolbarButton? {
if (s == null || s.isEmpty()) {
return null
}
val fields = s.split(Consts.FIELD_SEPARATOR.toRegex(), KEEP_EMPTY_ENTRIES.coerceAtLeast(0)).toTypedArray()
if (fields.size != 3) {
if (fields.size != 4) {
return null
}
val index: Int = try {
Expand All @@ -43,7 +45,7 @@ class CustomToolbarButton(var index: Int, private val prefix: String, private va
Timber.w(e)
return null
}
return CustomToolbarButton(index, fields[1], fields[2])
return CustomToolbarButton(index, fields[1], fields[2], fields[3])
}

@JvmStatic
Expand All @@ -66,7 +68,7 @@ class CustomToolbarButton(var index: Int, private val prefix: String, private va
fun toStringSet(buttons: ArrayList<CustomToolbarButton>): Set<String> {
val ret = HashSetInit<String>(buttons.size)
for (b in buttons) {
val values = arrayOf(b.index.toString(), b.prefix, b.suffix)
val values = arrayOf(b.index.toString(), b.buttonText, b.prefix, b.suffix)
for (i in values.indices) {
values[i] = values[i].replace(Consts.FIELD_SEPARATOR, "")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@ import androidx.annotation.VisibleForTesting
import androidx.core.content.edit
import com.ichi2.anki.AnkiDroidApp
import com.ichi2.anki.cardviewer.ViewerCommand
import com.ichi2.anki.noteeditor.CustomToolbarButton
import com.ichi2.anki.reviewer.Binding.Companion.keyCode
import com.ichi2.anki.reviewer.CardSide
import com.ichi2.anki.reviewer.FullScreenMode
import com.ichi2.anki.reviewer.MappableBinding
import com.ichi2.anki.web.CustomSyncServer
import com.ichi2.libanki.Consts
import com.ichi2.utils.HashUtil.HashSetInit
import timber.log.Timber

private typealias VersionIdentifier = Int
Expand Down Expand Up @@ -77,6 +80,7 @@ object PreferenceUpgradeService {
yield(LegacyPreferenceUpgrade(legacyPreviousVersionCode))
yield(UpgradeVolumeButtonsToBindings())
yield(RemoveLegacyMediaSyncUrl())
yield(UpdateNoteEditorToolbarPrefs())
}

/** Returns a list of preference upgrade classes which have not been applied */
Expand Down Expand Up @@ -230,5 +234,50 @@ object PreferenceUpgradeService {
}
}
}

/**
* update toolbar buttons with new preferences, when button text empty or null then it adds the index as button text
*/
internal class UpdateNoteEditorToolbarPrefs : PreferenceUpgrade(4) {
override fun upgrade(preferences: SharedPreferences) {
val buttons = getNewToolbarButtons(preferences)

// update prefs
preferences.edit {
remove("note_editor_custom_buttons")
putStringSet("note_editor_custom_buttons", CustomToolbarButton.toStringSet(buttons))
}
}

private fun getNewToolbarButtons(preferences: SharedPreferences): ArrayList<CustomToolbarButton> {
// get old toolbar prefs
val set = preferences.getStringSet("note_editor_custom_buttons", HashSetInit<String>(0)) as Set<String?>
// new list with buttons size
val buttons = ArrayList<CustomToolbarButton>(set.size)

// parse fields with separator
for (s in set) {
val fields = s!!.split(Consts.FIELD_SEPARATOR.toRegex(), CustomToolbarButton.KEEP_EMPTY_ENTRIES.coerceAtLeast(0)).toTypedArray()
if (fields.size != 3) {
continue
}

val index: Int = try {
fields[0].toInt()
} catch (e: Exception) {
Timber.w(e)
continue
}

// add new button with the index + 1 as button text
val visualIndex: Int = index + 1
val buttonText = visualIndex.toString()

// fields 1 is prefix, fields 2 is suffix
buttons.add(CustomToolbarButton(index, buttonText, fields[1], fields[2]))
}
return buttons
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@
android:text="@string/toolbar_item_explain_remove"
android:paddingBottom="15dp"/>

<com.google.android.material.textfield.TextInputLayout

android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/note_editor_toolbar_icon">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/note_editor_toolbar_item_icon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_vertical_padding"/>
</com.google.android.material.textfield.TextInputLayout>


<com.google.android.material.textfield.TextInputLayout

android:layout_width="match_parent"
Expand Down
1 change: 1 addition & 0 deletions AnkiDroid/src/main/res/values/02-strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@
<string name="insert_mathjax">Insert MathJax Equation</string>
<string name="insert_cloze">Insert Cloze Deletion</string>

<string name="note_editor_toolbar_icon">Button text</string>
<string name="before_text">HTML Before Selection</string>
<string name="after_text">HTML After Selection</string>
<string name="add_toolbar_item">Create Toolbar Item</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,22 @@
package com.ichi2.anki.servicemodel

import android.content.SharedPreferences
import android.text.TextUtils
import androidx.core.content.edit
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.ichi2.anki.AnkiDroidApp
import com.ichi2.anki.RobolectricTest
import com.ichi2.anki.noteeditor.CustomToolbarButton
import com.ichi2.anki.servicelayer.PreferenceUpgradeService
import com.ichi2.anki.servicelayer.PreferenceUpgradeService.PreferenceUpgrade
import com.ichi2.anki.web.CustomSyncServer
import com.ichi2.libanki.Consts
import com.ichi2.testutils.EmptyApplication
import com.ichi2.utils.HashUtil
import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.lessThan
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
Expand Down Expand Up @@ -111,4 +116,32 @@ class PreferenceUpgradeServiceTest : RobolectricTest() {
PreferenceUpgrade.RemoveLegacyMediaSyncUrl().performUpgrade(mPrefs)
assertThat("Preference of custom media sync url is removed.", CustomSyncServer.getMediaSyncUrl(mPrefs).equals(null))
}

@Test
fun note_editor_toolbar_button_text() {
// add two example toolbar buttons
val buttons = HashUtil.HashSetInit<String>(2)

var values = arrayOf(0, "<h1>", "</h1>")
buttons.add(TextUtils.join(Consts.FIELD_SEPARATOR, values))

values = arrayOf(1, "<p>", "</p>")
buttons.add(TextUtils.join(Consts.FIELD_SEPARATOR, values))

mPrefs.edit {
putStringSet("note_editor_custom_buttons", buttons)
}

// now update it and check it
PreferenceUpgrade.UpdateNoteEditorToolbarPrefs().performUpgrade(mPrefs)

val set = mPrefs.getStringSet("note_editor_custom_buttons", HashUtil.HashSetInit<String>(0)) as Set<String?>
val toolbarButtons = CustomToolbarButton.fromStringSet(set)

assertEquals("Set size", 2, set.size)
assertEquals("Toolbar buttons size", 2, toolbarButtons.size)

assertEquals("Button text prefs", "1", toolbarButtons[0].buttonText)
assertEquals("Button text prefs", "2", toolbarButtons[1].buttonText)
}
}

0 comments on commit 2bed6c3

Please sign in to comment.