Build the Ganjoor reader on the static ganjoor-data set

Poets grid, category browsing and a poem reader backed by
github.com/anas-rashid/ganjoor-data over jsDelivr — no backend, addressed by
Ganjoor URLs rather than numeric ids, with a 64 MB OkHttp disk cache so
anything already read stays readable offline.

Reading: couplets stack with the first hemistich at the start of the line and
the second at the end; prose sections fill the column. Bundled Noto Naskh
Arabic and Noto Nastaliq Urdu, switchable while reading, with the extra
leading nastaliq needs. Five themes (system, light, dark, sepia, sepia night)
and a text size slider, all persisted. Whole app lays out right-to-left.

Verified on an API 36 emulator through poets -> category -> poem in both
sepia schemes and both fonts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Anas RashidandClaude Opus 5 committed 2026-10-03 22:46:09 +02:00
1 parent 46ba109207
commit d9915eac6c
21 files changed
+1374 -138

No files matched your search

@@ -0,0 +1,68 @@
package com.ganjoor.android
import com.ganjoor.android.data.Verse
import com.ganjoor.android.data.couplets
import org.junit.Assert.assertEquals
import org.junit.Test
class CoupletsTest {
private fun verse(order: Int, position: String) =
Verse(vOrder = order, position = position, text = "v$order")
@Test
fun `right and left hemistichs pair into one couplet`() {
val grouped = listOf(
verse(1, Verse.RIGHT),
verse(2, Verse.LEFT),
verse(3, Verse.RIGHT),
verse(4, Verse.LEFT),
).couplets()
assertEquals(2, grouped.size)
assertEquals(listOf("v1", "v2"), grouped[0].map { it.text })
assertEquals(listOf("v3", "v4"), grouped[1].map { it.text })
}
@Test
fun `out of order verses are sorted before grouping`() {
val grouped = listOf(verse(2, Verse.LEFT), verse(1, Verse.RIGHT)).couplets()
assertEquals(1, grouped.size)
assertEquals(listOf("v1", "v2"), grouped[0].map { it.text })
}
@Test
fun `prose and single verses each stand alone`() {
val grouped = listOf(
verse(1, "Paragraph"),
verse(2, "Single"),
verse(3, Verse.RIGHT),
verse(4, Verse.LEFT),
).couplets()
assertEquals(listOf(1, 1, 2), grouped.map { it.size })
}
@Test
fun `a left hemistich without its right half is not swallowed by the previous couplet`() {
val grouped = listOf(
verse(1, Verse.RIGHT),
verse(2, Verse.LEFT),
verse(3, Verse.LEFT),
).couplets()
assertEquals(listOf(2, 1), grouped.map { it.size })
}
@Test
fun `centered verses pair with each other, not with hemistichs`() {
val grouped = listOf(
verse(1, Verse.CENTERED_1),
verse(2, Verse.CENTERED_2),
verse(3, Verse.RIGHT),
verse(4, Verse.CENTERED_2),
).couplets()
assertEquals(listOf(2, 1, 1), grouped.map { it.size })
}
}
@@ -1,17 +0,0 @@
package com.ganjoor.android
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}