General improvements (#316)
* Added support for right text alignment in epub reader * Added tabs management to PDF navigation drawer * Implemented unified selection menu placement logic * Added reset functionality for toolbar customization * Improved highlight filtering in epub pagination * Migrated hardcoded UI strings to string resources * Extracted desktop application logic from Main.kt into modular files * Refactored Main.kt by extracting PDF and EPUB logic into specialized files * Added Spanish language support * Added system default option to app language selection
This commit is contained in:
parent
759d4b73a0
commit
056485a140
77 changed files with 9184 additions and 5947 deletions
60
app/src/test/java/com/aryan/reader/AppLanguageOptionsTest.kt
Normal file
60
app/src/test/java/com/aryan/reader/AppLanguageOptionsTest.kt
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
package com.aryan.reader
|
||||
|
||||
import java.io.File
|
||||
import javax.xml.parsers.DocumentBuilderFactory
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
class AppLanguageOptionsTest {
|
||||
|
||||
@Test
|
||||
fun `supported app languages include Spanish`() {
|
||||
assertEquals(
|
||||
listOf("en", "ar", "de", "tr", "fr", "ru", "es"),
|
||||
supportedAppLanguageOptions.mapNotNull { it.tag }
|
||||
)
|
||||
assertEquals(R.string.language_spanish, supportedAppLanguageOptions.last().labelRes)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `app language selection defaults to system before explicit overrides`() {
|
||||
assertEquals(null, appLanguageSelectionOptions.first().tag)
|
||||
assertEquals(R.string.language_system_default, appLanguageSelectionOptions.first().labelRes)
|
||||
assertEquals(supportedAppLanguageOptions, appLanguageSelectionOptions.drop(1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `supported app language tags are unique`() {
|
||||
val tags = supportedAppLanguageOptions.mapNotNull { it.tag }
|
||||
|
||||
assertEquals(tags.distinct(), tags)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `supported app languages match Android locale config`() {
|
||||
assertEquals(readLocaleConfigTags(), supportedAppLanguageOptions.map { it.tag })
|
||||
}
|
||||
|
||||
private fun readLocaleConfigTags(): List<String> {
|
||||
val localeConfig = listOf(
|
||||
File("src/main/res/xml/locales_config.xml"),
|
||||
File("app/src/main/res/xml/locales_config.xml")
|
||||
).first { it.isFile }
|
||||
val document = DocumentBuilderFactory.newInstance()
|
||||
.apply { isNamespaceAware = true }
|
||||
.newDocumentBuilder()
|
||||
.parse(localeConfig)
|
||||
val localeNodes = document.getElementsByTagName("locale")
|
||||
|
||||
return buildList {
|
||||
for (index in 0 until localeNodes.length) {
|
||||
add(
|
||||
localeNodes.item(index)
|
||||
.attributes
|
||||
.getNamedItemNS("http://schemas.android.com/apk/res/android", "name")
|
||||
.nodeValue
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -198,4 +198,29 @@ class EpubReaderBridgeAndControlsTest {
|
|||
assertTrue(ReaderTool.entries.any { it.category == "Overflow Menu" })
|
||||
assertEquals("Top Bar", ReaderTool.SCREEN_ORIENTATION.category)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `reader toolbar reset defaults match first-run toolbar defaults`() {
|
||||
assertEquals(setOf(ReaderTool.SCREEN_ORIENTATION.name), defaultReaderHiddenTools())
|
||||
assertEquals(ReaderTool.entries.toList(), defaultReaderToolOrder())
|
||||
assertEquals(
|
||||
ReaderTool.entries.filter { it.category == "Bottom Bar" }.map { it.name }.toSet(),
|
||||
defaultReaderBottomTools()
|
||||
)
|
||||
|
||||
val defaultItems = buildReaderToolbarItems(
|
||||
hiddenTools = defaultReaderHiddenTools(),
|
||||
toolOrder = defaultReaderToolOrder(),
|
||||
bottomTools = defaultReaderBottomTools()
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
ToolbarSection.HIDDEN,
|
||||
defaultItems.single { it.tool == ReaderTool.SCREEN_ORIENTATION }.section
|
||||
)
|
||||
assertEquals(
|
||||
ToolbarSection.BOTTOM,
|
||||
defaultItems.single { it.tool == ReaderTool.SLIDER }.section
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class EpubReaderPreferencesAndAnnotationsTest {
|
|||
verticalMargin = 0.4f,
|
||||
fontFamily = ReaderFont.LORA,
|
||||
customFontPath = null,
|
||||
textAlign = ReaderTextAlign.JUSTIFY
|
||||
textAlign = ReaderTextAlign.RIGHT
|
||||
)
|
||||
saveLocalReaderSettings(
|
||||
context = context,
|
||||
|
|
@ -78,7 +78,7 @@ class EpubReaderPreferencesAndAnnotationsTest {
|
|||
|
||||
assertEquals(1.4f, global.fontSize, 0.0001f)
|
||||
assertEquals(ReaderFont.LORA, global.font)
|
||||
assertEquals(ReaderTextAlign.JUSTIFY, global.textAlign)
|
||||
assertEquals(ReaderTextAlign.RIGHT, global.textAlign)
|
||||
assertNull(global.customPath)
|
||||
assertEquals(0.9f, local.fontSize, 0.0001f)
|
||||
assertEquals(1.1f, local.lineHeight, 0.0001f)
|
||||
|
|
|
|||
|
|
@ -54,6 +54,35 @@ class PaginatedHighlightMappingTest {
|
|||
assertNull(getHighlightOffsetsInBlock(block, highlight))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `paginated page highlights are scoped to page chapter`() {
|
||||
val chapterFourHighlight = highlight(
|
||||
cfi = "/4/10:11|/4/12:79",
|
||||
text = "Original chapter text",
|
||||
chapterIndex = 4
|
||||
)
|
||||
val chapterFiveHighlight = highlight(
|
||||
cfi = "/4/10:11|/4/12:79",
|
||||
text = "Different chapter text",
|
||||
chapterIndex = 5
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
listOf(chapterFiveHighlight),
|
||||
highlightsForPaginatedPage(
|
||||
pageChapterIndex = 5,
|
||||
userHighlights = listOf(chapterFourHighlight, chapterFiveHighlight)
|
||||
)
|
||||
)
|
||||
assertEquals(
|
||||
emptyList<UserHighlight>(),
|
||||
highlightsForPaginatedPage(
|
||||
pageChapterIndex = null,
|
||||
userHighlights = listOf(chapterFourHighlight)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun paragraph(
|
||||
text: String,
|
||||
cfi: String,
|
||||
|
|
@ -70,14 +99,15 @@ class PaginatedHighlightMappingTest {
|
|||
|
||||
private fun highlight(
|
||||
cfi: String,
|
||||
text: String
|
||||
text: String,
|
||||
chapterIndex: Int = 0
|
||||
): UserHighlight {
|
||||
return UserHighlight(
|
||||
id = "highlight",
|
||||
cfi = cfi,
|
||||
text = text,
|
||||
color = HighlightColor.YELLOW,
|
||||
chapterIndex = 0
|
||||
chapterIndex = chapterIndex
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,4 +160,36 @@ class PdfReaderSettingsAndSharedModelsTest {
|
|||
assertTrue(width >= 1)
|
||||
assertTrue(height >= 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `pdf toolbar reset defaults match first-run toolbar defaults`() {
|
||||
assertEquals(
|
||||
setOf(PdfReaderTool.SCREEN_ORIENTATION.name, PdfReaderTool.HIGHLIGHT_ALL.name),
|
||||
defaultPdfHiddenTools()
|
||||
)
|
||||
assertEquals(PdfReaderTool.entries.toList(), defaultPdfToolOrder())
|
||||
assertEquals(
|
||||
PdfReaderTool.entries.filter { it.category == "Bottom Bar" }.map { it.name }.toSet(),
|
||||
defaultPdfBottomTools()
|
||||
)
|
||||
|
||||
val defaultItems = buildPdfToolbarItems(
|
||||
hiddenTools = defaultPdfHiddenTools(),
|
||||
toolOrder = defaultPdfToolOrder(),
|
||||
bottomTools = defaultPdfBottomTools()
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
PdfToolbarSection.HIDDEN,
|
||||
defaultItems.single { it.tool == PdfReaderTool.SCREEN_ORIENTATION }.section
|
||||
)
|
||||
assertEquals(
|
||||
PdfToolbarSection.HIDDEN,
|
||||
defaultItems.single { it.tool == PdfReaderTool.HIGHLIGHT_ALL }.section
|
||||
)
|
||||
assertEquals(
|
||||
PdfToolbarSection.BOTTOM,
|
||||
defaultItems.single { it.tool == PdfReaderTool.SLIDER }.section
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue