From a0ccd950a62f4c186144e9c858258574757c51ad Mon Sep 17 00:00:00 2001 From: ag2s20150909 Date: Fri, 2 Apr 2021 21:14:50 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E5=9C=A8io.legado.app.ui?= =?UTF-8?q?.book.cache.CacheViewModel=E4=B8=AD=E5=8A=A0=E5=85=A5=E5=AF=BC?= =?UTF-8?q?=E5=87=BAepub=E7=9A=84=E6=96=B9=E6=B3=95=EF=BC=88=E5=B0=81?= =?UTF-8?q?=E9=9D=A2=E6=9C=AA=E5=AE=9E=E7=8E=B0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/ui/book/cache/CacheViewModel.kt | 110 ++++++++++++++++++ .../java/me/ag2s/epublib/domain/Date.java | 8 +- .../me/ag2s/epublib/util/ResourceUtil.java | 24 +++- 3 files changed, 138 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt index d420372c6..927b570ed 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt @@ -13,7 +13,11 @@ import io.legado.app.help.BookHelp import io.legado.app.help.ContentProcessor import io.legado.app.help.storage.BookWebDav import io.legado.app.utils.* +import me.ag2s.epublib.domain.* +import me.ag2s.epublib.epub.EpubWriter +import me.ag2s.epublib.util.ResourceUtil import java.io.File +import java.io.FileOutputStream import java.nio.charset.Charset @@ -127,4 +131,110 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { } return srcList } + //////////////////Start EPUB + /** + * 导出Epub + */ + fun exportEPUB(path: String, book: Book, finally: (msg: String) -> Unit) { + execute { + if (path.isContentScheme()) { + val uri = Uri.parse(path) + DocumentFile.fromTreeUri(context, uri)?.let { + exportEpub(it, book) + } + } else { + exportEpub(FileUtils.createFolderIfNotExist(path), book) + } + }.onError { + finally(it.localizedMessage ?: "ERROR") + }.onSuccess { + finally(context.getString(R.string.success)) + } + } + + @Suppress("BlockingMethodInNonBlockingContext") + private suspend fun exportEpub(doc: DocumentFile, book: Book) { + val filename = "${book.name} by ${book.author}.epub" + DocumentUtils.delete(doc, filename) + val epubBook = EpubBook() + epubBook.version = "2.0" + //set metadata + setEpubMetadata(book,epubBook) + //set cover + //Todo + //epubBook.coverImage= Resource(FileInputStream(BookHelp.getImage(book, book.coverUrl)),"cover.jpg") + + //set css + epubBook.resources.add( + Resource( + "h1 {color: blue;}p {text-indent:2em;}".encodeToByteArray(), + "css/style.css" + ) + ) + //设置正文 + setEpubContent(book, epubBook) + + DocumentUtils.createFileIfNotExist(doc, filename)?.let { bookDoc -> + context.contentResolver.openOutputStream(bookDoc.uri, "wa")?.use { bookOs -> + EpubWriter().write(epubBook, bookOs) + } + + } + } + + private suspend fun exportEpub(file: File, book: Book) { + val filename = "${book.name} by ${book.author}.epub" + val epubBook = EpubBook() + epubBook.version = "2.0" + //set metadata + setEpubMetadata(book,epubBook) + //set cover + //Todo + //epubBook.coverImage= Resource(FileInputStream(BookHelp.getImage(book, book.coverUrl)),"cover.jpg") + + //set css + epubBook.resources.add( + Resource( + "h1 {color: blue;}p {text-indent:2em;}".encodeToByteArray(), + "css/style.css" + ) + ) + val bookPath = FileUtils.getPath(file, filename) + val bookFile = FileUtils.createFileWithReplace(bookPath) + //设置正文 + setEpubContent(book, epubBook) + EpubWriter().write(epubBook, FileOutputStream(bookFile)) + } + + private fun setEpubContent(book: Book, epubBook: EpubBook) { + val useReplace = AppConfig.exportUseReplace + val contentProcessor = ContentProcessor(book.name, book.origin) + appDb.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter -> + BookHelp.getContent(book, chapter).let { content -> + val content1 = contentProcessor + .getContent(book, chapter.title, content ?: "null", false, useReplace) + .joinToString("\n") + epubBook.addSection( + chapter.title, + ResourceUtil.createHTMLResource(chapter.title, content1) + ) + } + } + } + + private fun setEpubMetadata(book: Book,epubBook: EpubBook) { + val metadata = Metadata() + metadata.titles.add(book.name)//书籍的名称 + metadata.authors.add(Author(book.author))//书籍的作者 + metadata.language = "zh"//数据的语言 + metadata.dates.add(Date())//数据的创建日期 + metadata.publishers.add("Legado APP")//数据的创建者 + metadata.descriptions.add(book.getDisplayIntro())//书籍的简介 + //metadata.subjects.add("")//书籍的主题,在静读天下里面有使用这个分类书籍 + epubBook.metadata=metadata + } + + //////end of EPUB + + } \ No newline at end of file diff --git a/epublib/src/main/java/me/ag2s/epublib/domain/Date.java b/epublib/src/main/java/me/ag2s/epublib/domain/Date.java index b72990bca..8e25aba5d 100644 --- a/epublib/src/main/java/me/ag2s/epublib/domain/Date.java +++ b/epublib/src/main/java/me/ag2s/epublib/domain/Date.java @@ -1,11 +1,11 @@ package me.ag2s.epublib.domain; -import me.ag2s.epublib.epub.PackageDocumentBase; - import java.io.Serializable; import java.text.SimpleDateFormat; import java.util.Locale; +import me.ag2s.epublib.epub.PackageDocumentBase; + /** * A Date used by the book's metadata. *

@@ -48,6 +48,10 @@ public class Date implements Serializable { private Event event; private String dateString; + public Date() { + this(new java.util.Date(), Event.CREATION); + } + public Date(java.util.Date date) { this(date, (Event) null); } diff --git a/epublib/src/main/java/me/ag2s/epublib/util/ResourceUtil.java b/epublib/src/main/java/me/ag2s/epublib/util/ResourceUtil.java index ec742c0b0..96212f253 100644 --- a/epublib/src/main/java/me/ag2s/epublib/util/ResourceUtil.java +++ b/epublib/src/main/java/me/ag2s/epublib/util/ResourceUtil.java @@ -27,7 +27,12 @@ import me.ag2s.epublib.epub.EpubProcessorSupport; * @author paul */ public class ResourceUtil { - + /** + * 快速创建HTML类型的Resource + * @param title 章节的标题 + * @param string 章节的正文 + * @return 返回Resource + */ public static Resource createHTMLResource(String title, String string) { String html = createHtml(title, string); MediaType mediaTypeProperty = MediaTypes.XHTML; @@ -35,6 +40,14 @@ public class ResourceUtil { return new Resource(data, mediaTypeProperty); } + /** + * 快速创建HTML类型的Resource + * @param title 章节的标题 + * @param string 章节的正文 + * @param href Resource的href + * @return 返回Resource + */ + @SuppressWarnings("unused") public static Resource createHTMLResource(String title, String string, String href) { String html = createHtml(title, string); @@ -65,6 +78,13 @@ public class ResourceUtil { return html; } + /** + * 快速从File创建Resource + * @param file File + * @return + * @throws IOException + */ + @SuppressWarnings("unused") public static Resource createResource(File file) throws IOException { if (file == null) { @@ -77,7 +97,7 @@ public class ResourceUtil { /** - * Creates a resource with as contents a html page with the given title. + * 创建一个只带标题的HTMl类型的Resource,常用于封面页,大卷页 * * @param title v * @param href v From 1a8bdaf7e4df17f31949b630275ea13dbdb7c75f Mon Sep 17 00:00:00 2001 From: ag2s20150909 Date: Sat, 3 Apr 2021 00:57:32 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E5=B0=81=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../legado/app/ui/book/cache/CacheActivity.kt | 2 +- .../app/ui/book/cache/CacheViewModel.kt | 33 ++++++++++++++++--- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt index e01100bfd..52feb9489 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt @@ -239,7 +239,7 @@ class CacheActivity : VMBaseActivity() adapter.getItem(exportPosition)?.let { book -> Snackbar.make(binding.titleBar, R.string.exporting, Snackbar.LENGTH_INDEFINITE) .show() - viewModel.export(path, book) { + viewModel.exportEPUB(path, book) { binding.titleBar.snackbar(it) } } diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt index 927b570ed..92b8bf238 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt @@ -1,8 +1,14 @@ package io.legado.app.ui.book.cache import android.app.Application +import android.content.Context +import android.graphics.Bitmap +import android.graphics.drawable.Drawable import android.net.Uri import androidx.documentfile.provider.DocumentFile +import com.bumptech.glide.Glide +import com.bumptech.glide.request.target.CustomTarget +import com.bumptech.glide.request.transition.Transition import io.legado.app.R import io.legado.app.base.BaseViewModel import io.legado.app.constant.AppPattern @@ -16,6 +22,7 @@ import io.legado.app.utils.* import me.ag2s.epublib.domain.* import me.ag2s.epublib.epub.EpubWriter import me.ag2s.epublib.util.ResourceUtil +import java.io.ByteArrayOutputStream import java.io.File import java.io.FileOutputStream import java.nio.charset.Charset @@ -161,8 +168,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { //set metadata setEpubMetadata(book,epubBook) //set cover - //Todo - //epubBook.coverImage= Resource(FileInputStream(BookHelp.getImage(book, book.coverUrl)),"cover.jpg") + setCover(book, epubBook) //set css epubBook.resources.add( @@ -189,8 +195,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { //set metadata setEpubMetadata(book,epubBook) //set cover - //Todo - //epubBook.coverImage= Resource(FileInputStream(BookHelp.getImage(book, book.coverUrl)),"cover.jpg") + setCover(book, epubBook) //set css epubBook.resources.add( @@ -205,6 +210,26 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { setEpubContent(book, epubBook) EpubWriter().write(epubBook, FileOutputStream(bookFile)) } + private fun setCover(book: Book, epubBook: EpubBook) { + + Glide.with(context) + .asBitmap() + .load(book.coverUrl) + .into(object : CustomTarget(){ + override fun onResourceReady(resource: Bitmap, transition: Transition?) { + val stream = ByteArrayOutputStream() + resource.compress(Bitmap.CompressFormat.JPEG, 100, stream) + val byteArray: ByteArray = stream.toByteArray() + resource.recycle() + epubBook.coverImage= Resource(byteArray,"cover.jpg") + } + + override fun onLoadCleared(placeholder: Drawable?) { + + } + + }) + } private fun setEpubContent(book: Book, epubBook: EpubBook) { val useReplace = AppConfig.exportUseReplace From 925b407b889f807f46842fa4abf3baad59453b70 Mon Sep 17 00:00:00 2001 From: ag2s20150909 Date: Sat, 3 Apr 2021 07:47:13 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=A0=87=E9=A2=98?= =?UTF-8?q?=E9=87=8D=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/legado/app/ui/book/cache/CacheViewModel.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt index 92b8bf238..e60a7d3d0 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt @@ -1,7 +1,6 @@ package io.legado.app.ui.book.cache import android.app.Application -import android.content.Context import android.graphics.Bitmap import android.graphics.drawable.Drawable import android.net.Uri @@ -239,6 +238,8 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { val content1 = contentProcessor .getContent(book, chapter.title, content ?: "null", false, useReplace) .joinToString("\n") + .replace(chapter.title,"") + epubBook.addSection( chapter.title, ResourceUtil.createHTMLResource(chapter.title, content1)