🚀 Add and Improve Parsers
Added new supported file extensions: ".zip", ".html" and ".htm". Improved parsers: ".epub". Partly Resolves(no ".cbz"): #48
This commit is contained in:
parent
5e2cc28c92
commit
e1fdac0f39
13 changed files with 987 additions and 536 deletions
|
|
@ -2,8 +2,11 @@ package ua.acclorite.book_story.data.parser
|
|||
|
||||
import ua.acclorite.book_story.data.parser.epub.EpubFileParser
|
||||
import ua.acclorite.book_story.data.parser.fb2.Fb2FileParser
|
||||
import ua.acclorite.book_story.data.parser.htm.HtmFileParser
|
||||
import ua.acclorite.book_story.data.parser.html.HtmlFileParser
|
||||
import ua.acclorite.book_story.data.parser.pdf.PdfFileParser
|
||||
import ua.acclorite.book_story.data.parser.txt.TxtFileParser
|
||||
import ua.acclorite.book_story.data.parser.zip.ZipFileParser
|
||||
import ua.acclorite.book_story.domain.model.Book
|
||||
import ua.acclorite.book_story.domain.util.CoverImage
|
||||
import java.io.File
|
||||
|
|
@ -13,32 +16,48 @@ class FileParserImpl @Inject constructor(
|
|||
private val txtFileParser: TxtFileParser,
|
||||
private val pdfFileParser: PdfFileParser,
|
||||
private val epubFileParser: EpubFileParser,
|
||||
private val fb2FileParser: Fb2FileParser
|
||||
private val fb2FileParser: Fb2FileParser,
|
||||
private val zipFileParser: ZipFileParser,
|
||||
private val htmlFileParser: HtmlFileParser,
|
||||
private val htmFileParser: HtmFileParser,
|
||||
) : FileParser {
|
||||
override suspend fun parse(file: File): Pair<Book, CoverImage?>? {
|
||||
if (!file.exists()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val fileFormat = ".${file.name.substringAfterLast(".")}".lowercase().trim()
|
||||
|
||||
if (fileFormat == ".pdf") {
|
||||
return pdfFileParser.parse(file)
|
||||
val fileFormat = ".${file.extension}".lowercase().trim()
|
||||
return when (fileFormat) {
|
||||
".pdf" -> {
|
||||
pdfFileParser.parse(file)
|
||||
}
|
||||
|
||||
if (fileFormat == ".epub") {
|
||||
return epubFileParser.parse(file)
|
||||
".epub" -> {
|
||||
epubFileParser.parse(file)
|
||||
}
|
||||
|
||||
if (fileFormat == ".txt") {
|
||||
return txtFileParser.parse(file)
|
||||
".txt" -> {
|
||||
txtFileParser.parse(file)
|
||||
}
|
||||
|
||||
if (fileFormat == ".fb2") {
|
||||
return fb2FileParser.parse(file)
|
||||
".fb2" -> {
|
||||
fb2FileParser.parse(file)
|
||||
}
|
||||
|
||||
return null
|
||||
".zip" -> {
|
||||
zipFileParser.parse(file)
|
||||
}
|
||||
|
||||
".html" -> {
|
||||
htmlFileParser.parse(file)
|
||||
}
|
||||
|
||||
".htm" -> {
|
||||
htmFileParser.parse(file)
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
package ua.acclorite.book_story.data.parser
|
||||
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.data.parser.epub.EpubTextParser
|
||||
import ua.acclorite.book_story.data.parser.fb2.Fb2TextParser
|
||||
import ua.acclorite.book_story.data.parser.htm.HtmTextParser
|
||||
import ua.acclorite.book_story.data.parser.html.HtmlTextParser
|
||||
import ua.acclorite.book_story.data.parser.pdf.PdfTextParser
|
||||
import ua.acclorite.book_story.data.parser.txt.TxtTextParser
|
||||
import ua.acclorite.book_story.data.parser.zip.ZipTextParser
|
||||
import ua.acclorite.book_story.domain.util.Resource
|
||||
import ua.acclorite.book_story.domain.util.UIText
|
||||
import java.io.File
|
||||
|
|
@ -13,8 +15,11 @@ import javax.inject.Inject
|
|||
class TextParserImpl @Inject constructor(
|
||||
private val txtTextParser: TxtTextParser,
|
||||
private val pdfTextParser: PdfTextParser,
|
||||
private val epubTextParser: EpubTextParser,
|
||||
private val fb2TextParser: Fb2TextParser
|
||||
private val epubTextParser: HtmlTextParser,
|
||||
private val fb2TextParser: Fb2TextParser,
|
||||
private val zipTextParser: ZipTextParser,
|
||||
private val htmlTextParser: HtmlTextParser,
|
||||
private val htmTextParser: HtmTextParser,
|
||||
) : TextParser {
|
||||
override suspend fun parse(file: File): Resource<List<String>> {
|
||||
if (!file.exists()) {
|
||||
|
|
@ -23,25 +28,38 @@ class TextParserImpl @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
val fileFormat = ".${file.name.substringAfterLast(".")}".lowercase().trim()
|
||||
|
||||
if (fileFormat == ".pdf") {
|
||||
return pdfTextParser.parse(file)
|
||||
val fileFormat = ".${file.extension}".lowercase().trim()
|
||||
return when (fileFormat) {
|
||||
".pdf" -> {
|
||||
pdfTextParser.parse(file)
|
||||
}
|
||||
|
||||
if (fileFormat == ".epub") {
|
||||
return epubTextParser.parse(file)
|
||||
".epub" -> {
|
||||
epubTextParser.parse(file)
|
||||
}
|
||||
|
||||
if (fileFormat == ".txt") {
|
||||
return txtTextParser.parse(file)
|
||||
".txt" -> {
|
||||
txtTextParser.parse(file)
|
||||
}
|
||||
|
||||
if (fileFormat == ".fb2") {
|
||||
return fb2TextParser.parse(file)
|
||||
".fb2" -> {
|
||||
fb2TextParser.parse(file)
|
||||
}
|
||||
|
||||
return Resource.Error(UIText.StringResource(R.string.error_wrong_file_format))
|
||||
".zip" -> {
|
||||
zipTextParser.parse(file)
|
||||
}
|
||||
|
||||
".html" -> {
|
||||
htmlTextParser.parse(file)
|
||||
}
|
||||
|
||||
".htm" -> {
|
||||
htmTextParser.parse(file)
|
||||
}
|
||||
|
||||
else -> Resource.Error(UIText.StringResource(R.string.error_wrong_file_format))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import android.graphics.BitmapFactory
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jsoup.Jsoup
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.data.parser.FileParser
|
||||
import ua.acclorite.book_story.domain.model.Book
|
||||
import ua.acclorite.book_story.domain.model.Category
|
||||
|
|
@ -36,27 +37,40 @@ class EpubFileParser @Inject constructor() : FileParser {
|
|||
.use { it.readText() }
|
||||
val document = Jsoup.parse(opfContent)
|
||||
|
||||
val title = document.select("metadata > dc|title").text().trim()
|
||||
val author = UIText.StringValue(
|
||||
document.select("metadata > dc|creator").text().trim()
|
||||
)
|
||||
val description = Jsoup.parse(
|
||||
document.select("metadata > dc|description").text()
|
||||
).text()
|
||||
|
||||
var coverImagePath: String? = null
|
||||
|
||||
val coverId = document
|
||||
.select("metadata > meta[name=cover]")
|
||||
.attr("content")
|
||||
if (coverId.isNotBlank()) {
|
||||
coverImagePath = document
|
||||
.select("manifest > item[id=$coverId]")
|
||||
.attr("href")
|
||||
val title = document.select("metadata > dc|title").text().trim().run {
|
||||
ifBlank {
|
||||
file.nameWithoutExtension.trim()
|
||||
}
|
||||
}
|
||||
|
||||
if (coverImagePath.isNullOrBlank()) {
|
||||
coverImagePath = document
|
||||
val author = document.select("metadata > dc|creator").text().trim().run {
|
||||
if (isBlank()) {
|
||||
UIText.StringResource(R.string.unknown_author)
|
||||
} else {
|
||||
UIText.StringValue(this)
|
||||
}
|
||||
}
|
||||
|
||||
val description = Jsoup.parse(
|
||||
document.select("metadata > dc|description").text()
|
||||
).text().run {
|
||||
ifBlank {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val coverImage = document
|
||||
.select("metadata > meta[name=cover]")
|
||||
.attr("content")
|
||||
.run {
|
||||
if (isNotBlank()) {
|
||||
document
|
||||
.select("manifest > item[id=$this]")
|
||||
.attr("href")
|
||||
.apply { if (isNotBlank()) return@run this }
|
||||
}
|
||||
|
||||
document
|
||||
.select("manifest > item[media-type*=image]")
|
||||
.firstOrNull()?.attr("href")
|
||||
}
|
||||
|
|
@ -73,7 +87,7 @@ class EpubFileParser @Inject constructor() : FileParser {
|
|||
lastOpened = null,
|
||||
category = Category.entries[0],
|
||||
coverImage = null
|
||||
) to extractCoverImageBitmap(file, coverImagePath)
|
||||
) to extractCoverImageBitmap(file, coverImage)
|
||||
}
|
||||
}
|
||||
return book
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class Fb2FileParser @Inject constructor() : FileParser {
|
|||
}
|
||||
|
||||
val titleFromFile = extractElementContent(document, "book-title")
|
||||
val title = titleFromFile ?: file.name.dropLast(4).trim()
|
||||
val title = titleFromFile ?: file.nameWithoutExtension.trim()
|
||||
|
||||
val authorFirstName = extractElementContent(document, "first-name")
|
||||
val authorLastName = extractElementContent(document, "last-name")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
package ua.acclorite.book_story.data.parser.htm
|
||||
|
||||
import org.jsoup.Jsoup
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.data.parser.FileParser
|
||||
import ua.acclorite.book_story.domain.model.Book
|
||||
import ua.acclorite.book_story.domain.model.Category
|
||||
import ua.acclorite.book_story.domain.util.CoverImage
|
||||
import ua.acclorite.book_story.domain.util.UIText
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
class HtmFileParser @Inject constructor() : FileParser {
|
||||
|
||||
override suspend fun parse(file: File): Pair<Book, CoverImage?>? {
|
||||
if (!file.name.endsWith(".htm", true) || !file.exists()) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
val document = Jsoup.parse(file)
|
||||
|
||||
val title = document.select("head > title").text().trim().run {
|
||||
ifBlank {
|
||||
file.nameWithoutExtension.trim()
|
||||
}
|
||||
}
|
||||
|
||||
return Book(
|
||||
title = title,
|
||||
author = UIText.StringResource(R.string.unknown_author),
|
||||
description = null,
|
||||
textPath = "",
|
||||
scrollIndex = 0,
|
||||
scrollOffset = 0,
|
||||
progress = 0f,
|
||||
filePath = file.path,
|
||||
lastOpened = null,
|
||||
category = Category.entries[0],
|
||||
coverImage = null
|
||||
) to null
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package ua.acclorite.book_story.data.parser.htm
|
||||
|
||||
import org.jsoup.Jsoup
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.data.parser.TextParser
|
||||
import ua.acclorite.book_story.domain.util.Resource
|
||||
import ua.acclorite.book_story.domain.util.UIText
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class HtmTextParser @Inject constructor() : TextParser {
|
||||
|
||||
override suspend fun parse(file: File): Resource<List<String>> {
|
||||
if (!file.name.endsWith(".htm", true) || !file.exists()) {
|
||||
return Resource.Error(UIText.StringResource(R.string.error_wrong_file_format))
|
||||
}
|
||||
|
||||
try {
|
||||
val lines = mutableListOf<String>()
|
||||
|
||||
val document = Jsoup.parse(file)
|
||||
document.select("p").append("\n")
|
||||
document
|
||||
.wholeText()
|
||||
.lines()
|
||||
.forEach { line ->
|
||||
if (line.isNotBlank()) {
|
||||
lines.add(line.trim())
|
||||
}
|
||||
}
|
||||
|
||||
if (lines.isEmpty()) {
|
||||
return Resource.Error(UIText.StringResource(R.string.error_file_empty))
|
||||
}
|
||||
|
||||
return Resource.Success(lines)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return Resource.Error(
|
||||
UIText.StringResource(
|
||||
R.string.error_query,
|
||||
e.message?.take(40)?.trim() ?: ""
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package ua.acclorite.book_story.data.parser.html
|
||||
|
||||
import org.jsoup.Jsoup
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.data.parser.FileParser
|
||||
import ua.acclorite.book_story.domain.model.Book
|
||||
import ua.acclorite.book_story.domain.model.Category
|
||||
import ua.acclorite.book_story.domain.util.CoverImage
|
||||
import ua.acclorite.book_story.domain.util.UIText
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
class HtmlFileParser @Inject constructor() : FileParser {
|
||||
|
||||
override suspend fun parse(file: File): Pair<Book, CoverImage?>? {
|
||||
if (!file.name.endsWith(".html", true) || !file.exists()) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
val document = Jsoup.parse(file)
|
||||
|
||||
val title = document.select("head > title").text().trim().run {
|
||||
ifBlank {
|
||||
file.nameWithoutExtension.trim()
|
||||
}
|
||||
}
|
||||
|
||||
return Book(
|
||||
title = title,
|
||||
author = UIText.StringResource(R.string.unknown_author),
|
||||
description = null,
|
||||
textPath = "",
|
||||
scrollIndex = 0,
|
||||
scrollOffset = 0,
|
||||
progress = 0f,
|
||||
filePath = file.path,
|
||||
lastOpened = null,
|
||||
category = Category.entries[0],
|
||||
coverImage = null
|
||||
) to null
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package ua.acclorite.book_story.data.parser.html
|
||||
|
||||
import org.jsoup.Jsoup
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.data.parser.TextParser
|
||||
import ua.acclorite.book_story.domain.util.Resource
|
||||
import ua.acclorite.book_story.domain.util.UIText
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class HtmlTextParser @Inject constructor() : TextParser {
|
||||
|
||||
override suspend fun parse(file: File): Resource<List<String>> {
|
||||
if (!file.name.endsWith(".html", true) || !file.exists()) {
|
||||
return Resource.Error(UIText.StringResource(R.string.error_wrong_file_format))
|
||||
}
|
||||
|
||||
try {
|
||||
val lines = mutableListOf<String>()
|
||||
|
||||
val document = Jsoup.parse(file)
|
||||
document.select("p").append("\n")
|
||||
document
|
||||
.wholeText()
|
||||
.lines()
|
||||
.forEach { line ->
|
||||
if (line.isNotBlank()) {
|
||||
lines.add(line.trim())
|
||||
}
|
||||
}
|
||||
|
||||
if (lines.isEmpty()) {
|
||||
return Resource.Error(UIText.StringResource(R.string.error_file_empty))
|
||||
}
|
||||
|
||||
return Resource.Success(lines)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return Resource.Error(
|
||||
UIText.StringResource(
|
||||
R.string.error_query,
|
||||
e.message?.take(40)?.trim() ?: ""
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,10 +24,11 @@ class PdfFileParser @Inject constructor(private val application: Application) :
|
|||
|
||||
val document = PDDocument.load(file)
|
||||
|
||||
val title = document.documentInformation.title ?: file.name.dropLast(4).trim()
|
||||
val fileAuthor = document.documentInformation.author
|
||||
val author = if (fileAuthor != null) UIText.StringValue(fileAuthor)
|
||||
else UIText.StringResource(R.string.unknown_author)
|
||||
val title = document.documentInformation.title ?: file.nameWithoutExtension.trim()
|
||||
val author = document.documentInformation.author.run {
|
||||
if (isNullOrBlank()) UIText.StringResource(R.string.unknown_author)
|
||||
else UIText.StringValue(this)
|
||||
}
|
||||
val description = document.documentInformation.subject ?: null
|
||||
|
||||
document.close()
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class TxtFileParser @Inject constructor() : FileParser {
|
|||
}
|
||||
|
||||
try {
|
||||
val title = file.name.trim().dropLast(4)
|
||||
val title = file.nameWithoutExtension.trim()
|
||||
val author = UIText.StringResource(R.string.unknown_author)
|
||||
|
||||
return Book(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,116 @@
|
|||
package ua.acclorite.book_story.data.parser.zip
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jsoup.Jsoup
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.data.parser.FileParser
|
||||
import ua.acclorite.book_story.domain.model.Book
|
||||
import ua.acclorite.book_story.domain.model.Category
|
||||
import ua.acclorite.book_story.domain.util.CoverImage
|
||||
import ua.acclorite.book_story.domain.util.UIText
|
||||
import java.io.File
|
||||
import java.util.zip.ZipFile
|
||||
import javax.inject.Inject
|
||||
|
||||
class ZipFileParser @Inject constructor() : FileParser {
|
||||
|
||||
override suspend fun parse(file: File): Pair<Book, CoverImage?>? {
|
||||
if (!file.name.endsWith(".zip", true) || !file.exists()) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
var book: Pair<Book, CoverImage?>? = null
|
||||
|
||||
withContext(Dispatchers.IO) {
|
||||
ZipFile(file).use { zip ->
|
||||
val opfEntry = zip.entries().asSequence().find { entry ->
|
||||
entry.name.endsWith(".opf")
|
||||
} ?: return@withContext
|
||||
|
||||
val opfContent = zip
|
||||
.getInputStream(opfEntry)
|
||||
.bufferedReader()
|
||||
.use { it.readText() }
|
||||
val document = Jsoup.parse(opfContent)
|
||||
|
||||
val title = document.select("metadata > dc|title").text().trim().run {
|
||||
ifBlank {
|
||||
file.nameWithoutExtension.trim()
|
||||
}
|
||||
}
|
||||
|
||||
val author = document.select("metadata > dc|creator").text().trim().run {
|
||||
if (isBlank()) {
|
||||
UIText.StringResource(R.string.unknown_author)
|
||||
} else {
|
||||
UIText.StringValue(this)
|
||||
}
|
||||
}
|
||||
|
||||
val description = Jsoup.parse(
|
||||
document.select("metadata > dc|description").text()
|
||||
).text().run {
|
||||
ifBlank {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val coverImage = document
|
||||
.select("metadata > meta[name=cover]")
|
||||
.attr("content")
|
||||
.run {
|
||||
if (isNotBlank()) {
|
||||
document
|
||||
.select("manifest > item[id=$this]")
|
||||
.attr("href")
|
||||
.apply { if (isNotBlank()) return@run this }
|
||||
}
|
||||
|
||||
document
|
||||
.select("manifest > item[media-type*=image]")
|
||||
.firstOrNull()?.attr("href")
|
||||
}
|
||||
|
||||
book = Book(
|
||||
title = title,
|
||||
author = author,
|
||||
description = description,
|
||||
textPath = "",
|
||||
scrollIndex = 0,
|
||||
scrollOffset = 0,
|
||||
progress = 0f,
|
||||
filePath = file.path,
|
||||
lastOpened = null,
|
||||
category = Category.entries[0],
|
||||
coverImage = null
|
||||
) to extractCoverImageBitmap(file, coverImage)
|
||||
}
|
||||
}
|
||||
return book
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractCoverImageBitmap(file: File, coverImagePath: String?): Bitmap? {
|
||||
if (coverImagePath.isNullOrBlank()) {
|
||||
return null
|
||||
}
|
||||
|
||||
ZipFile(file).use { zip ->
|
||||
zip.entries().asSequence().forEach { entry ->
|
||||
if (entry.name.endsWith(coverImagePath)) {
|
||||
val imageBytes = zip.getInputStream(entry).readBytes()
|
||||
return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package ua.acclorite.book_story.data.parser.zip
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jsoup.Jsoup
|
||||
import ua.acclorite.book_story.R
|
||||
import ua.acclorite.book_story.data.parser.TextParser
|
||||
import ua.acclorite.book_story.domain.util.Resource
|
||||
import ua.acclorite.book_story.domain.util.UIText
|
||||
import java.io.File
|
||||
import java.util.zip.ZipFile
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class ZipTextParser @Inject constructor() : TextParser {
|
||||
|
||||
override suspend fun parse(file: File): Resource<List<String>> {
|
||||
if (!file.name.endsWith(".zip", true) || !file.exists()) {
|
||||
return Resource.Error(UIText.StringResource(R.string.error_wrong_file_format))
|
||||
}
|
||||
|
||||
try {
|
||||
val lines = mutableListOf<String>()
|
||||
|
||||
withContext(Dispatchers.IO) {
|
||||
ZipFile(file).use { zip ->
|
||||
zip.entries().asSequence().forEach { entry ->
|
||||
if (
|
||||
entry.name.endsWith(".xhtml")
|
||||
|| entry.name.endsWith(".html")
|
||||
|| entry.name.endsWith(".xml")
|
||||
|| entry.name.endsWith(".htm")
|
||||
) {
|
||||
val content = zip.getInputStream(entry).bufferedReader()
|
||||
.use {
|
||||
it.readText()
|
||||
}
|
||||
|
||||
val document = Jsoup.parse(content)
|
||||
document.select("p").append("\n")
|
||||
document
|
||||
.wholeText()
|
||||
.lines()
|
||||
.forEach { line ->
|
||||
if (line.isNotBlank()) {
|
||||
lines.add(line.trim())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lines.isEmpty()) {
|
||||
return Resource.Error(UIText.StringResource(R.string.error_file_empty))
|
||||
}
|
||||
|
||||
return Resource.Success(lines)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return Resource.Error(
|
||||
UIText.StringResource(
|
||||
R.string.error_query,
|
||||
e.message?.take(40)?.trim() ?: ""
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,16 +27,46 @@ object Constants {
|
|||
const val MAIN_STATE = "main_state"
|
||||
|
||||
// Supported file extensions
|
||||
val EXTENSIONS = listOf(".epub", ".pdf", ".fb2", ".txt")
|
||||
val EXTENSIONS = provideSupportedExtensions()
|
||||
|
||||
// Supported languages
|
||||
val LANGUAGES = listOf(
|
||||
Pair("en", "English"),
|
||||
Pair("uk", "Українська"),
|
||||
)
|
||||
val LANGUAGES = provideLanguages()
|
||||
|
||||
// Navigation items for NavigationBars.
|
||||
val NAVIGATION_ITEMS = listOf(
|
||||
val NAVIGATION_ITEMS = provideNavigationItems()
|
||||
|
||||
// Supported themes
|
||||
val THEMES = provideThemes()
|
||||
|
||||
// Credits
|
||||
val CREDITS = provideCredits()
|
||||
|
||||
// Help Tips
|
||||
val HELP_TIPS = provideHelpTips()
|
||||
|
||||
// About Badges
|
||||
val ABOUT_BADGES = provideAboutBadges()
|
||||
|
||||
// Fonts for Reader
|
||||
val FONTS = provideFonts()
|
||||
|
||||
// Empty Book (Used for Default Screen values)
|
||||
val EMPTY_BOOK = provideEmptyBook()
|
||||
|
||||
// Default Color Preset (Used when creating new color presets)
|
||||
val DEFAULT_COLOR_PRESET = provideDefaultColorPreset()
|
||||
}
|
||||
|
||||
private fun provideSupportedExtensions() = listOf(
|
||||
".epub", ".pdf", ".fb2", ".txt", ".zip", ".html", ".htm"
|
||||
)
|
||||
|
||||
private fun provideLanguages() = listOf(
|
||||
Pair("en", "English"),
|
||||
Pair("uk", "Українська"),
|
||||
)
|
||||
|
||||
private fun provideNavigationItems() = listOf(
|
||||
NavigationItem(
|
||||
screen = Screen.Library,
|
||||
title = R.string.library_screen,
|
||||
|
|
@ -58,10 +88,9 @@ object Constants {
|
|||
selectedIcon = R.drawable.browse_screen_filled,
|
||||
unselectedIcon = R.drawable.browse_screen_outlined
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// Supported themes
|
||||
val THEMES = listOf(
|
||||
private fun provideThemes() = listOf(
|
||||
Pair(Theme.DYNAMIC, UIText.StringResource(R.string.dynamic_theme)),
|
||||
Pair(Theme.BLUE, UIText.StringResource(R.string.blue_theme)),
|
||||
Pair(Theme.GREEN, UIText.StringResource(R.string.green_theme)),
|
||||
|
|
@ -70,10 +99,9 @@ object Constants {
|
|||
Pair(Theme.PINK, UIText.StringResource(R.string.pink_theme)),
|
||||
Pair(Theme.YELLOW, UIText.StringResource(R.string.yellow_theme)),
|
||||
Pair(Theme.AQUA, UIText.StringResource(R.string.aqua_theme)),
|
||||
)
|
||||
)
|
||||
|
||||
// Credits
|
||||
val CREDITS = listOf(
|
||||
private fun provideCredits() = listOf(
|
||||
Credit(
|
||||
name = "Tachiyomi (Mihon)",
|
||||
source = "GitHub",
|
||||
|
|
@ -99,10 +127,9 @@ object Constants {
|
|||
),
|
||||
website = "https://fonts.google.com/icons"
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
// Help Tips
|
||||
val HELP_TIPS = listOf(
|
||||
private fun provideHelpTips() = listOf(
|
||||
HelpTip(
|
||||
title = R.string.help_title_how_to_find_books,
|
||||
description = { _, _ ->
|
||||
|
|
@ -329,10 +356,9 @@ object Constants {
|
|||
append(stringResource(id = R.string.help_desc_how_to_use_color_presets_1))
|
||||
}
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
// About Badges
|
||||
val ABOUT_BADGES = listOf(
|
||||
private fun provideAboutBadges() = listOf(
|
||||
Badge(
|
||||
id = "x",
|
||||
drawable = R.drawable.x_logo,
|
||||
|
|
@ -368,10 +394,9 @@ object Constants {
|
|||
contentDescription = R.string.github_profile_content_desc,
|
||||
url = "https://www.github.com/Acclorite"
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
// Fonts for Reader
|
||||
val FONTS = listOf(
|
||||
private fun provideFonts() = listOf(
|
||||
FontWithName(
|
||||
"default",
|
||||
UIText.StringResource(R.string.default_font),
|
||||
|
|
@ -496,9 +521,9 @@ object Constants {
|
|||
Font(R.font.lora_regular_italic, style = FontStyle.Italic)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val EMPTY_BOOK = Book(
|
||||
private fun provideEmptyBook() = Book(
|
||||
id = -1,
|
||||
title = "",
|
||||
author = UIText.StringValue(""),
|
||||
|
|
@ -511,13 +536,12 @@ object Constants {
|
|||
progress = 0f,
|
||||
lastOpened = null,
|
||||
category = Category.READING
|
||||
)
|
||||
)
|
||||
|
||||
val DEFAULT_COLOR_PRESET = ColorPreset(
|
||||
private fun provideDefaultColorPreset() = ColorPreset(
|
||||
id = -1,
|
||||
name = null,
|
||||
backgroundColor = Color.DarkGray,
|
||||
fontColor = Color.LightGray,
|
||||
isSelected = false
|
||||
)
|
||||
}
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue