Skip to content

Commit e487267

Browse files
committed
Update layout constraints for gesture display images
1 parent b653143 commit e487267

File tree

6 files changed

+102
-21
lines changed

6 files changed

+102
-21
lines changed

AnkiDroid/src/main/assets/scripts/js-api.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ class AnkiDroidJS {
121121
Object.keys(jsApiList).forEach(method => {
122122
if (method === "ankiAddTagToNote") {
123123
AnkiDroidJS.prototype[method] = async function (noteId, tag) {
124-
console.warn("ankiAddTagToNote is deprecated. Use ankiSetNoteTags instead.");
124+
console.warn("ankiAddTagToNote is deprecated. Use ankiSetNoteTags instead");
125125
const endpoint = jsApiList[method];
126126
const data = JSON.stringify({ noteId, tag });
127127
return await this.handleRequest(endpoint, data);
@@ -130,6 +130,17 @@ Object.keys(jsApiList).forEach(method => {
130130
}
131131
if (method === "ankiSetNoteTags") {
132132
AnkiDroidJS.prototype[method] = async function (noteId, tags) {
133+
let hasSpaces = false;
134+
for (let i = 0; i < tags.length; i++) {
135+
tags[i] = tags[i].trim();
136+
if (tags[i].includes(" ") || tags[i].includes("\u3000")) {
137+
tags[i] = tags[i].replace(" ", "_").replace("\u3000", "_");
138+
hasSpaces = true;
139+
}
140+
}
141+
if (hasSpaces) {
142+
console.warn("Spaces in tags have been converted to underscores");
143+
}
133144
const endpoint = jsApiList[method];
134145
const data = JSON.stringify({ noteId, tags });
135146
return await this.handleRequest(endpoint, data);

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ open class AnkiDroidJsAPI(
206206
* @param returnDefaultValues `true` if default values should be returned (if non-[Reviewer])
207207
* @return
208208
*/
209+
@NeedsTest("setNoteTags: Test that tags are set for all edge cases")
209210
open suspend fun handleJsApiRequest(
210211
methodName: String,
211212
bytes: ByteArray,
@@ -383,7 +384,12 @@ open class AnkiDroidJsAPI(
383384
val tags = jsonObject.getJSONArray("tags")
384385
withCol {
385386
fun Note.setTagsFromList(tagList: List<String>) {
386-
val tagsAsString = this@withCol.tags.join(tagList)
387+
val sanitizedTags = tagList.map { it.trim() }
388+
val spaces = "\\s|\u3000".toRegex()
389+
if (sanitizedTags.any { it.contains(spaces) }) {
390+
throw IllegalArgumentException("Tags cannot contain spaces")
391+
}
392+
val tagsAsString = this@withCol.tags.join(sanitizedTags)
387393
setTagsFromStr(this@withCol, tagsAsString)
388394
}
389395

AnkiDroid/src/main/res/layout/activity_shared_decks.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
android:layout_height="wrap_content"
1818
android:minHeight="?attr/actionBarSize"
1919
android:theme="@style/ActionBarStyle"
20-
android:background="?attr/colorPrimary"
20+
android:background="?attr/appBarColor"
2121
app:popupTheme="@style/ActionBar.Popup"
2222
app:layout_constraintTop_toTopOf="parent"
2323
app:layout_constraintStart_toStartOf="parent"

AnkiDroid/src/main/res/layout/gesture_display.xml

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,33 +25,41 @@
2525
<ImageView
2626
android:id="@+id/top_left"
2727
style="@style/binding_gesture_tap_button"
28-
android:layout_marginStart="16dp"
29-
android:layout_marginTop="16dp"
28+
app:layout_constraintHorizontal_bias="0.047"
29+
app:layout_constraintVertical_bias="0.047"
30+
app:layout_constraintBottom_toBottomOf="parent"
31+
app:layout_constraintEnd_toEndOf="parent"
3032
app:layout_constraintStart_toStartOf="parent"
3133
app:layout_constraintTop_toTopOf="parent" />
3234

3335
<ImageView
3436
android:id="@+id/top_center"
3537
style="@style/binding_gesture_tap_button"
36-
android:layout_marginTop="16dp"
38+
app:layout_constraintVertical_bias="0.047"
39+
app:layout_constraintBottom_toBottomOf="parent"
3740
app:layout_constraintEnd_toEndOf="parent"
3841
app:layout_constraintStart_toStartOf="parent"
3942
app:layout_constraintTop_toTopOf="parent" />
4043

4144
<ImageView
4245
android:id="@+id/top_right"
4346
style="@style/binding_gesture_tap_button"
44-
app:layout_constraintEnd_toEndOf="@+id/right"
45-
app:layout_constraintTop_toTopOf="@+id/top_center" />
47+
app:layout_constraintHorizontal_bias="0.953"
48+
app:layout_constraintVertical_bias="0.047"
49+
app:layout_constraintBottom_toBottomOf="parent"
50+
app:layout_constraintEnd_toEndOf="parent"
51+
app:layout_constraintStart_toStartOf="parent"
52+
app:layout_constraintTop_toTopOf="parent" />
4653

4754

4855
<ImageView
4956
android:id="@+id/left"
5057
style="@style/binding_gesture_tap_button"
51-
android:layout_marginStart="16dp"
52-
app:layout_constraintBottom_toTopOf="parent"
58+
app:layout_constraintHorizontal_bias="0.047"
59+
app:layout_constraintBottom_toBottomOf="parent"
60+
app:layout_constraintEnd_toEndOf="parent"
5361
app:layout_constraintStart_toStartOf="parent"
54-
app:layout_constraintTop_toBottomOf="parent" />
62+
app:layout_constraintTop_toTopOf="parent" />
5563

5664
<ImageView
5765
android:id="@+id/center"
@@ -64,33 +72,40 @@
6472
<ImageView
6573
android:id="@+id/right"
6674
style="@style/binding_gesture_tap_button"
67-
android:layout_marginEnd="16dp"
68-
app:layout_constraintBottom_toTopOf="parent"
75+
app:layout_constraintHorizontal_bias="0.953"
76+
app:layout_constraintBottom_toBottomOf="parent"
6977
app:layout_constraintEnd_toEndOf="parent"
70-
app:layout_constraintTop_toBottomOf="parent" />
78+
app:layout_constraintStart_toStartOf="parent"
79+
app:layout_constraintTop_toTopOf="parent" />
7180

7281
<ImageView
7382
android:id="@+id/bottom_left"
74-
android:layout_marginBottom="16dp"
7583
style="@style/binding_gesture_tap_button"
84+
app:layout_constraintHorizontal_bias="0.047"
85+
app:layout_constraintVertical_bias="0.953"
7686
app:layout_constraintBottom_toBottomOf="parent"
77-
app:layout_constraintStart_toStartOf="@+id/left" />
87+
app:layout_constraintEnd_toEndOf="parent"
88+
app:layout_constraintStart_toStartOf="parent"
89+
app:layout_constraintTop_toTopOf="parent" />
7890

7991
<ImageView
8092
android:id="@+id/bottom_center"
8193
style="@style/binding_gesture_tap_button"
82-
android:layout_marginBottom="16dp"
94+
app:layout_constraintVertical_bias="0.953"
8395
app:layout_constraintBottom_toBottomOf="parent"
8496
app:layout_constraintEnd_toEndOf="parent"
85-
app:layout_constraintStart_toStartOf="parent" />
97+
app:layout_constraintStart_toStartOf="parent"
98+
app:layout_constraintTop_toTopOf="parent" />
8699

87100
<ImageView
88101
android:id="@+id/bottom_right"
89102
style="@style/binding_gesture_tap_button"
90-
android:layout_marginEnd="16dp"
91-
android:layout_marginBottom="16dp"
103+
app:layout_constraintHorizontal_bias="0.953"
104+
app:layout_constraintVertical_bias="0.953"
92105
app:layout_constraintBottom_toBottomOf="parent"
93-
app:layout_constraintEnd_toEndOf="parent" />
106+
app:layout_constraintEnd_toEndOf="parent"
107+
app:layout_constraintStart_toStartOf="parent"
108+
app:layout_constraintTop_toTopOf="parent" />
94109

95110
<ImageView
96111
android:id="@+id/swipe_select"

AnkiDroid/src/test/java/com/ichi2/anki/AnkiDroidJsAPITest.kt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import com.ichi2.utils.BASIC_MODEL_NAME
2828
import net.ankiweb.rsdroid.withoutUnicodeIsolation
2929
import org.hamcrest.CoreMatchers.equalTo
3030
import org.hamcrest.MatcherAssert.assertThat
31+
import org.json.JSONArray
3132
import org.json.JSONObject
3233
import org.junit.Ignore
3334
import org.junit.Test
@@ -418,6 +419,31 @@ class AnkiDroidJsAPITest : RobolectricTest() {
418419
assertEquals(CardType.New, cardAfterReset.type, "Card type after reset")
419420
}
420421

422+
@Test
423+
fun ankiGetNoteTagsTest() =
424+
runTest {
425+
val n =
426+
addBasicNote("Front", "Back").update {
427+
tags = mutableListOf("tag1", "tag2", "tag3")
428+
}
429+
430+
val reviewer: Reviewer = startReviewer()
431+
waitForAsyncTasksToComplete()
432+
433+
val jsapi = reviewer.jsApi
434+
435+
// test get tags for note
436+
val expectedTags = n.tags
437+
val response = getDataFromRequest("getNoteTags", jsapi, jsonObjectOf("noteId" to n.id))
438+
val jsonResponse = JSONObject(response)
439+
val actualTags = JSONArray(jsonResponse.getString("value"))
440+
441+
assertEquals(expectedTags.size, actualTags.length())
442+
for (i in 0 until actualTags.length()) {
443+
assertEquals(expectedTags[i], actualTags.getString(i))
444+
}
445+
}
446+
421447
companion object {
422448
fun jsApiContract(data: String = ""): ByteArray =
423449
JSONObject()
@@ -451,5 +477,21 @@ class AnkiDroidJsAPITest : RobolectricTest() {
451477
jsAPI
452478
.handleJsApiRequest(methodName, jsApiContract(apiData), false)
453479
.decodeToString()
480+
481+
suspend fun getDataFromRequest(
482+
methodName: String,
483+
jsAPI: AnkiDroidJsAPI,
484+
apiData: JSONObject,
485+
): String =
486+
jsAPI
487+
.handleJsApiRequest(methodName, jsApiContract(apiData.toString()), false)
488+
.decodeToString()
454489
}
455490
}
491+
492+
private fun jsonObjectOf(vararg pairs: Pair<String, Any>): JSONObject =
493+
JSONObject().apply {
494+
for ((key, value) in pairs) {
495+
put(key, value)
496+
}
497+
}

AnkiDroid/src/test/java/com/ichi2/testutils/TestClass.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,13 @@ interface TestClass {
241241
col.decks.save(deckConfig)
242242
}
243243

244+
/** Helper method to update a note */
245+
fun Note.update(block: Note.() -> Unit): Note {
246+
block(this)
247+
col.updateNote(this)
248+
return this
249+
}
250+
244251
/** Helper method to all cards of a note */
245252
fun Note.updateCards(update: Card.() -> Unit): Note {
246253
cards().forEach { it.update(update) }

0 commit comments

Comments
 (0)