kunfei пре 3 година
родитељ
комит
d746142ced

+ 15 - 24
app/src/main/java/io/legado/app/ui/book/bookmark/AllBookmarkViewModel.kt

@@ -2,41 +2,32 @@ package io.legado.app.ui.book.bookmark
 
 
 import android.app.Application
 import android.app.Application
 import android.net.Uri
 import android.net.Uri
-import androidx.documentfile.provider.DocumentFile
 import io.legado.app.base.BaseViewModel
 import io.legado.app.base.BaseViewModel
 import io.legado.app.constant.AppLog
 import io.legado.app.constant.AppLog
 import io.legado.app.data.appDb
 import io.legado.app.data.appDb
-import io.legado.app.utils.*
-import java.io.File
-import java.io.FileOutputStream
+import io.legado.app.utils.FileDoc
+import io.legado.app.utils.GSON
+import io.legado.app.utils.createFileIfNotExist
+import io.legado.app.utils.openOutputStream
+import io.legado.app.utils.toastOnUi
+import io.legado.app.utils.writeToOutputStream
 import java.text.SimpleDateFormat
 import java.text.SimpleDateFormat
-import java.util.*
+import java.util.Date
+import java.util.Locale
 
 
 class AllBookmarkViewModel(application: Application) : BaseViewModel(application) {
 class AllBookmarkViewModel(application: Application) : BaseViewModel(application) {
 
 
 
 
-    @Suppress("BlockingMethodInNonBlockingContext")
+    /**
+     * 导出书签
+     */
     fun saveToFile(treeUri: Uri) {
     fun saveToFile(treeUri: Uri) {
         execute {
         execute {
             val dateFormat = SimpleDateFormat("yyMMddHHmmss", Locale.getDefault())
             val dateFormat = SimpleDateFormat("yyMMddHHmmss", Locale.getDefault())
-            val bookmark = appDb.bookmarkDao.all
-            if (treeUri.isContentScheme()) {
-                val doc = DocumentFile.fromTreeUri(context, treeUri)
-                    ?.createFile("", "bookmark-${dateFormat.format(Date())}")
-                doc?.let {
-                    context.contentResolver.openOutputStream(doc.uri)!!.use {
-                        GSON.writeToOutputStream(it, bookmark)
-                    }
-                }
-            } else {
-                val path = treeUri.path!!
-                val file = FileUtils.createFileIfNotExist(
-                    File(path),
-                    "bookmark-${dateFormat.format(Date())}"
-                )
-                FileOutputStream(file).use {
-                    GSON.writeToOutputStream(it, bookmark)
-                }
+            val fileName = "bookmark-${dateFormat.format(Date())}"
+            val dirDoc = FileDoc.fromUri(treeUri, true)
+            dirDoc.createFileIfNotExist(fileName).openOutputStream().getOrThrow().use {
+                GSON.writeToOutputStream(it, appDb.bookmarkDao.all)
             }
             }
         }.onError {
         }.onError {
             AppLog.put("导出失败\n${it.localizedMessage}", it, true)
             AppLog.put("导出失败\n${it.localizedMessage}", it, true)

+ 1 - 1
app/src/main/java/io/legado/app/ui/book/toc/TocActivity.kt

@@ -157,7 +157,7 @@ class TocActivity : VMBaseActivity<ActivityChapterListBinding, TocViewModel>(),
                 viewModel.chapterListCallBack?.upChapterList(searchView?.query?.toString())
                 viewModel.chapterListCallBack?.upChapterList(searchView?.query?.toString())
             }
             }
 
 
-            R.id.menu_export -> exportDir.launch()
+            R.id.menu_export_bookmark -> exportDir.launch()
 
 
             R.id.menu_log -> showDialogFragment<AppLogDialog>()
             R.id.menu_log -> showDialogFragment<AppLogDialog>()
         }
         }

+ 9 - 32
app/src/main/java/io/legado/app/ui/book/toc/TocViewModel.kt

@@ -3,7 +3,6 @@ package io.legado.app.ui.book.toc
 
 
 import android.app.Application
 import android.app.Application
 import android.net.Uri
 import android.net.Uri
-import androidx.documentfile.provider.DocumentFile
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.MutableLiveData
 import io.legado.app.R
 import io.legado.app.R
 import io.legado.app.base.BaseViewModel
 import io.legado.app.base.BaseViewModel
@@ -12,16 +11,11 @@ import io.legado.app.data.appDb
 import io.legado.app.data.entities.Book
 import io.legado.app.data.entities.Book
 import io.legado.app.exception.NoStackTraceException
 import io.legado.app.exception.NoStackTraceException
 import io.legado.app.model.localBook.LocalBook
 import io.legado.app.model.localBook.LocalBook
-import io.legado.app.utils.FileUtils
+import io.legado.app.utils.FileDoc
 import io.legado.app.utils.GSON
 import io.legado.app.utils.GSON
-import io.legado.app.utils.isContentScheme
+import io.legado.app.utils.createFileIfNotExist
 import io.legado.app.utils.toastOnUi
 import io.legado.app.utils.toastOnUi
-import io.legado.app.utils.writeToOutputStream
-import java.io.File
-import java.io.FileOutputStream
-import java.text.SimpleDateFormat
-import java.util.Date
-import java.util.Locale
+import io.legado.app.utils.writeText
 
 
 class TocViewModel(application: Application) : BaseViewModel(application) {
 class TocViewModel(application: Application) : BaseViewModel(application) {
     var bookUrl: String = ""
     var bookUrl: String = ""
@@ -78,34 +72,17 @@ class TocViewModel(application: Application) : BaseViewModel(application) {
         bookMarkCallBack?.upBookmark(newText)
         bookMarkCallBack?.upBookmark(newText)
     }
     }
 
 
-    @Suppress("BlockingMethodInNonBlockingContext")
     fun saveBookmark(treeUri: Uri) {
     fun saveBookmark(treeUri: Uri) {
         execute {
         execute {
             val book = bookData.value
             val book = bookData.value
                 ?: throw NoStackTraceException(context.getString(R.string.no_book))
                 ?: throw NoStackTraceException(context.getString(R.string.no_book))
-            val dateFormat = SimpleDateFormat("yyMMddHHmmss", Locale.getDefault())
-            val bookmark = appDb.bookmarkDao.getByBook(book.name, book.author)
-            if (treeUri.isContentScheme()) {
-                val doc = DocumentFile.fromTreeUri(context, treeUri)
-                    ?.createFile("", "bookmark-${dateFormat.format(Date())}")
-                doc?.let {
-                    context.contentResolver.openOutputStream(doc.uri)!!.use {
-                        GSON.writeToOutputStream(it, bookmark)
-                    }
-                }
-            } else {
-                val path = treeUri.path!!
-                val file = FileUtils.createFileIfNotExist(
-                    File(path), "bookmark-${
-                        dateFormat.format(
-                            Date()
-                        )
-                    }"
+            val fileName = "bookmark-${book.name} ${book.author}"
+            val doc = FileDoc.fromUri(treeUri, true)
+            doc.createFileIfNotExist(fileName).writeText(
+                GSON.toJson(
+                    appDb.bookmarkDao.getByBook(book.name, book.author)
                 )
                 )
-                FileOutputStream(file).use {
-                    GSON.writeToOutputStream(it, bookmark)
-                }
-            }
+            )
         }.onError {
         }.onError {
             AppLog.put("导出失败\n${it.localizedMessage}", it, true)
             AppLog.put("导出失败\n${it.localizedMessage}", it, true)
         }.onSuccess {
         }.onSuccess {

+ 4 - 0
app/src/main/java/io/legado/app/utils/FileDocExtensions.kt

@@ -232,6 +232,10 @@ fun FileDoc.openInputStream(): Result<InputStream> {
     return uri.inputStream(appCtx)
     return uri.inputStream(appCtx)
 }
 }
 
 
+fun FileDoc.openOutputStream(): Result<OutputStream> {
+    return uri.outputStream(appCtx)
+}
+
 fun FileDoc.exists(
 fun FileDoc.exists(
     fileName: String,
     fileName: String,
     vararg subDirs: String
     vararg subDirs: String

+ 28 - 0
app/src/main/java/io/legado/app/utils/UriExtensions.kt

@@ -17,7 +17,9 @@ import okio.source
 import splitties.init.appCtx
 import splitties.init.appCtx
 import java.io.File
 import java.io.File
 import java.io.FileInputStream
 import java.io.FileInputStream
+import java.io.FileOutputStream
 import java.io.InputStream
 import java.io.InputStream
+import java.io.OutputStream
 import java.nio.charset.Charset
 import java.nio.charset.Charset
 
 
 fun Uri.isContentScheme() = this.scheme == "content"
 fun Uri.isContentScheme() = this.scheme == "content"
@@ -204,6 +206,32 @@ fun Uri.inputStream(context: Context): Result<InputStream> {
     }
     }
 }
 }
 
 
+fun Uri.outputStream(context: Context): Result<OutputStream> {
+    val uri = this
+    return kotlin.runCatching {
+        try {
+            if (isContentScheme()) {
+                DocumentFile.fromSingleUri(context, uri)
+                    ?: throw NoStackTraceException("未获取到文件")
+                return@runCatching context.contentResolver.openOutputStream(uri)!!
+            } else {
+                val path = RealPathUtil.getPath(context, uri)
+                    ?: throw NoStackTraceException("未获取到文件")
+                val file = File(path)
+                if (file.exists()) {
+                    return@runCatching FileOutputStream(file)
+                } else {
+                    throw NoStackTraceException("文件不存在")
+                }
+            }
+        } catch (e: Exception) {
+            e.printOnDebug()
+            AppLog.put("读取inputStream失败:${e.localizedMessage}", e)
+            throw e
+        }
+    }
+}
+
 fun Uri.toRequestBody(contentType: MediaType? = null): RequestBody {
 fun Uri.toRequestBody(contentType: MediaType? = null): RequestBody {
     val uri = this
     val uri = this
     return object : RequestBody() {
     return object : RequestBody() {