Skip to content

Commit ce8e3f2

Browse files
committed
Allow search to show subdecks if they match the searched term
1 parent 25d8511 commit ce8e3f2

File tree

2 files changed

+115
-1
lines changed

2 files changed

+115
-1
lines changed

AnkiDroid/src/main/java/com/ichi2/libanki/sched/DeckNode.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,13 @@ data class DeckNode(
113113
return
114114
}
115115

116-
if (collapsed) {
116+
// When searching, ignore collapsed state and always search children
117+
val searching = filter != null
118+
if (collapsed && !searching) {
117119
return
118120
}
121+
// TODO: Fix collapse/uncollapse icons showing during search even when they are not usable.
122+
// See issue #18379 for more details.
119123

120124
if (node.level > 0) {
121125
list.append(this)
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/****************************************************************************************
2+
* *
3+
* Copyright (c) 2025 Shridhar Goel <shridhar.goel@gmail.com> *
4+
* *
5+
* This program is free software; you can redistribute it and/or modify it under *
6+
* the terms of the GNU General Public License as published by the Free Software *
7+
* Foundation; either version 3 of the License, or (at your option) any later *
8+
* version. *
9+
* *
10+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY *
11+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
12+
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
13+
* *
14+
* You should have received a copy of the GNU General Public License along with *
15+
* this program. If not, see <http://www.gnu.org/licenses/>. *
16+
****************************************************************************************/
17+
18+
package com.ichi2.libanki
19+
20+
import anki.decks.deckTreeNode
21+
import com.ichi2.libanki.sched.DeckNode
22+
import org.junit.Assert.assertEquals
23+
import org.junit.Test
24+
25+
class DeckNodeTest {
26+
private fun makeNode(
27+
name: String,
28+
deckId: Long,
29+
level: Int,
30+
collapsed: Boolean = false,
31+
children: List<DeckNode> = emptyList(),
32+
): DeckNode {
33+
val treeNode =
34+
deckTreeNode {
35+
this.name = name
36+
this.deckId = deckId
37+
this.level = level
38+
this.collapsed = collapsed
39+
children.forEach { this.children.add(it.node) }
40+
this.reviewCount = 0
41+
this.newCount = 0
42+
this.learnCount = 0
43+
this.filtered = false
44+
}
45+
return DeckNode(treeNode, name)
46+
}
47+
48+
@Test
49+
fun `search finds subdeck even if parent collapsed`() {
50+
// Science::Math::Algebra::Group
51+
val group = makeNode("Group", 4, 4)
52+
val algebra = makeNode("Algebra", 3, 3, children = listOf(group))
53+
val math = makeNode("Math", 2, 2, collapsed = true, children = listOf(algebra))
54+
val science = makeNode("Science", 1, 1, children = listOf(math))
55+
56+
val results1 = science.filterAndFlatten("group")
57+
assertEquals(listOf("Science", "Math", "Algebra", "Group"), results1.map { it.lastDeckNameComponent })
58+
59+
val results2 = science.filterAndFlatten("math")
60+
assertEquals(listOf("Science", "Math"), results2.map { it.lastDeckNameComponent })
61+
}
62+
63+
@Test
64+
fun `collapsed parent hides children when not searching`() {
65+
val group = makeNode("Group", 4, 4)
66+
val algebra = makeNode("Algebra", 3, 3, children = listOf(group))
67+
val math = makeNode("Math", 2, 2, collapsed = true, children = listOf(algebra))
68+
val science = makeNode("Science", 1, 1, children = listOf(math))
69+
70+
val results = math.filterAndFlatten(null)
71+
assertEquals(1, results.size)
72+
assertEquals("Math", results[0].lastDeckNameComponent)
73+
}
74+
75+
@Test
76+
fun `search for non-matching term returns no results`() {
77+
// Science::Math::Algebra::Group
78+
val group = makeNode("Group", 4, 4)
79+
val algebra = makeNode("Algebra", 3, 3, children = listOf(group))
80+
val math = makeNode("Math", 2, 2, collapsed = true, children = listOf(algebra))
81+
val science = makeNode("Science", 1, 1, children = listOf(math))
82+
83+
val results = science.filterAndFlatten("complex")
84+
assertEquals(emptyList<String>(), results.map { it.lastDeckNameComponent })
85+
}
86+
87+
@Test
88+
fun `search for algebra shows all decks in the path`() {
89+
// Science::Math::Algebra::Group
90+
val group = makeNode("Group", 4, 4)
91+
val algebra = makeNode("Algebra", 3, 3, children = listOf(group))
92+
val math = makeNode("Math", 2, 2, collapsed = false, children = listOf(algebra))
93+
val science = makeNode("Science", 1, 1, children = listOf(math))
94+
95+
val results = science.filterAndFlatten("algebra")
96+
assertEquals(listOf("Science", "Math", "Algebra", "Group"), results.map { it.lastDeckNameComponent })
97+
}
98+
99+
@Test
100+
fun `search for non-existent path pattern returns no results`() {
101+
// Science::Math::Algebra::Group
102+
val group = makeNode("Group", 4, 4)
103+
val algebra = makeNode("Algebra", 3, 3, children = listOf(group))
104+
val math = makeNode("Math", 2, 2, collapsed = false, children = listOf(algebra))
105+
val science = makeNode("Science", 1, 1, children = listOf(math))
106+
107+
val results = science.filterAndFlatten("th::alg")
108+
assertEquals(emptyList<String>(), results.map { it.lastDeckNameComponent })
109+
}
110+
}

0 commit comments

Comments
 (0)