This commit is contained in:
kunfei
2023-07-29 17:11:23 +08:00
parent 0df551c194
commit b625d067e0
6 changed files with 119 additions and 23 deletions
@@ -20,12 +20,17 @@ import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.theme.primaryTextColor import io.legado.app.lib.theme.primaryTextColor
import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.ui.book.read.ReadBookActivity
import io.legado.app.ui.book.search.SearchActivity import io.legado.app.ui.book.search.SearchActivity
import io.legado.app.utils.* import io.legado.app.utils.applyTint
import io.legado.app.utils.cnCompare
import io.legado.app.utils.getInt
import io.legado.app.utils.putInt
import io.legado.app.utils.startActivity
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale
class ReadRecordActivity : BaseActivity<ActivityReadRecordBinding>() { class ReadRecordActivity : BaseActivity<ActivityReadRecordBinding>() {
@@ -149,7 +154,7 @@ class ReadRecordActivity : BaseActivity<ActivityReadRecordBinding>() {
inner class RecordAdapter(context: Context) : inner class RecordAdapter(context: Context) :
RecyclerAdapter<ReadRecordShow, ItemReadRecordBinding>(context) { RecyclerAdapter<ReadRecordShow, ItemReadRecordBinding>(context) {
private val dateFormat = SimpleDateFormat("yyyy-MM-dd") private val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
override fun getViewBinding(parent: ViewGroup): ItemReadRecordBinding { override fun getViewBinding(parent: ViewGroup): ItemReadRecordBinding {
return ItemReadRecordBinding.inflate(inflater, parent, false) return ItemReadRecordBinding.inflate(inflater, parent, false)
@@ -1,10 +1,10 @@
package io.legado.app.ui.book.bookmark package io.legado.app.ui.book.bookmark
import android.annotation.SuppressLint
import android.app.Application import android.app.Application
import android.net.Uri import android.net.Uri
import androidx.documentfile.provider.DocumentFile 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.data.appDb import io.legado.app.data.appDb
import io.legado.app.utils.* import io.legado.app.utils.*
import java.io.File import java.io.File
@@ -16,25 +16,32 @@ class AllBookmarkViewModel(application: Application) : BaseViewModel(application
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
@SuppressLint("SimpleDateFormat")
fun saveToFile(treeUri: Uri) { fun saveToFile(treeUri: Uri) {
execute { execute {
val dateFormat = SimpleDateFormat("yyMMddHHmmss") val dateFormat = SimpleDateFormat("yyMMddHHmmss", Locale.getDefault())
val bookmark = appDb.bookmarkDao.all
if (treeUri.isContentScheme()) { if (treeUri.isContentScheme()) {
val doc = DocumentFile.fromTreeUri(context, treeUri) val doc = DocumentFile.fromTreeUri(context, treeUri)
?.createFile("", "bookmark-${dateFormat.format(Date())}") ?.createFile("", "bookmark-${dateFormat.format(Date())}")
doc?.let { doc?.let {
context.contentResolver.openOutputStream(doc.uri)!!.use { context.contentResolver.openOutputStream(doc.uri)!!.use {
GSON.writeToOutputStream(it, appDb.bookmarkDao.all) GSON.writeToOutputStream(it, bookmark)
} }
} }
} else { } else {
val path = treeUri.path!! val path = treeUri.path!!
val file = FileUtils.createFileIfNotExist(File(path), "bookmark-${dateFormat.format(Date())}") val file = FileUtils.createFileIfNotExist(
File(path),
"bookmark-${dateFormat.format(Date())}"
)
FileOutputStream(file).use { FileOutputStream(file).use {
GSON.writeToOutputStream(it, appDb.bookmarkDao.all) GSON.writeToOutputStream(it, bookmark)
} }
} }
}.onError {
AppLog.put("导出失败\n${it.localizedMessage}", it, true)
}.onSuccess {
context.toastOnUi("导出成功")
} }
} }
@@ -24,6 +24,7 @@ import io.legado.app.lib.theme.primaryTextColor
import io.legado.app.model.ReadBook import io.legado.app.model.ReadBook
import io.legado.app.ui.about.AppLogDialog import io.legado.app.ui.about.AppLogDialog
import io.legado.app.ui.book.toc.rule.TxtTocRuleDialog import io.legado.app.ui.book.toc.rule.TxtTocRuleDialog
import io.legado.app.ui.file.HandleFileContract
import io.legado.app.ui.widget.dialog.WaitDialog import io.legado.app.ui.widget.dialog.WaitDialog
import io.legado.app.utils.* import io.legado.app.utils.*
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
@@ -41,6 +42,11 @@ class TocActivity : VMBaseActivity<ActivityChapterListBinding, TocViewModel>(),
private var menu: Menu? = null private var menu: Menu? = null
private var searchView: SearchView? = null private var searchView: SearchView? = null
private val waitDialog by lazy { WaitDialog(this) } private val waitDialog by lazy { WaitDialog(this) }
private val exportDir = registerForActivityResult(HandleFileContract()) {
it.uri?.let { uri ->
viewModel.saveBookmark(uri)
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
tabLayout = binding.titleBar.findViewById(R.id.tab_layout) tabLayout = binding.titleBar.findViewById(R.id.tab_layout)
@@ -71,9 +77,6 @@ class TocActivity : VMBaseActivity<ActivityChapterListBinding, TocViewModel>(),
override fun onCompatCreateOptionsMenu(menu: Menu): Boolean { override fun onCompatCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.book_toc, menu) menuInflater.inflate(R.menu.book_toc, menu)
this.menu = menu this.menu = menu
viewModel.bookData.value?.let {
menu.setGroupVisible(R.id.menu_group_text, it.isLocalTxt)
}
val search = menu.findItem(R.id.menu_search) val search = menu.findItem(R.id.menu_search)
searchView = (search.actionView as SearchView).apply { searchView = (search.actionView as SearchView).apply {
applyTint(primaryTextColor) applyTint(primaryTextColor)
@@ -110,6 +113,15 @@ class TocActivity : VMBaseActivity<ActivityChapterListBinding, TocViewModel>(),
} }
override fun onMenuOpened(featureId: Int, menu: Menu): Boolean { override fun onMenuOpened(featureId: Int, menu: Menu): Boolean {
if (tabLayout.selectedTabPosition == 1) {
menu.setGroupVisible(R.id.menu_group_bookmark, true)
menu.setGroupVisible(R.id.menu_group_toc, false)
menu.setGroupVisible(R.id.menu_group_text, false)
} else {
menu.setGroupVisible(R.id.menu_group_bookmark, false)
menu.setGroupVisible(R.id.menu_group_toc, true)
menu.setGroupVisible(R.id.menu_group_text, viewModel.bookData.value?.isLocalTxt == true)
}
menu.findItem(R.id.menu_use_replace)?.isChecked = menu.findItem(R.id.menu_use_replace)?.isChecked =
AppConfig.tocUiUseReplace AppConfig.tocUiUseReplace
menu.findItem(R.id.menu_split_long_chapter)?.isChecked = menu.findItem(R.id.menu_split_long_chapter)?.isChecked =
@@ -122,6 +134,7 @@ class TocActivity : VMBaseActivity<ActivityChapterListBinding, TocViewModel>(),
R.id.menu_toc_regex -> showDialogFragment( R.id.menu_toc_regex -> showDialogFragment(
TxtTocRuleDialog(viewModel.bookData.value?.tocUrl) TxtTocRuleDialog(viewModel.bookData.value?.tocUrl)
) )
R.id.menu_split_long_chapter -> { R.id.menu_split_long_chapter -> {
viewModel.bookData.value?.let { book -> viewModel.bookData.value?.let { book ->
item.isChecked = !item.isChecked item.isChecked = !item.isChecked
@@ -129,6 +142,7 @@ class TocActivity : VMBaseActivity<ActivityChapterListBinding, TocViewModel>(),
upBookAndToc(book) upBookAndToc(book)
} }
} }
R.id.menu_reverse_toc -> viewModel.reverseToc { R.id.menu_reverse_toc -> viewModel.reverseToc {
viewModel.chapterListCallBack?.upChapterList(searchView?.query?.toString()) viewModel.chapterListCallBack?.upChapterList(searchView?.query?.toString())
setResult(RESULT_OK, Intent().apply { setResult(RESULT_OK, Intent().apply {
@@ -136,11 +150,15 @@ class TocActivity : VMBaseActivity<ActivityChapterListBinding, TocViewModel>(),
putExtra("chapterPos", 0) putExtra("chapterPos", 0)
}) })
} }
R.id.menu_use_replace -> { R.id.menu_use_replace -> {
AppConfig.tocUiUseReplace = !item.isChecked AppConfig.tocUiUseReplace = !item.isChecked
viewModel.chapterListCallBack?.clearDisplayTitle() viewModel.chapterListCallBack?.clearDisplayTitle()
viewModel.chapterListCallBack?.upChapterList(searchView?.query?.toString()) viewModel.chapterListCallBack?.upChapterList(searchView?.query?.toString())
} }
R.id.menu_export -> exportDir.launch()
R.id.menu_log -> showDialogFragment<AppLogDialog>() R.id.menu_log -> showDialogFragment<AppLogDialog>()
} }
return super.onCompatOptionsItemSelected(item) return super.onCompatOptionsItemSelected(item)
@@ -2,11 +2,26 @@ package io.legado.app.ui.book.toc
import android.app.Application import android.app.Application
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.base.BaseViewModel import io.legado.app.base.BaseViewModel
import io.legado.app.constant.AppLog
import io.legado.app.data.appDb 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.model.localBook.LocalBook import io.legado.app.model.localBook.LocalBook
import io.legado.app.utils.FileUtils
import io.legado.app.utils.GSON
import io.legado.app.utils.isContentScheme
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
class TocViewModel(application: Application) : BaseViewModel(application) { class TocViewModel(application: Application) : BaseViewModel(application) {
var bookUrl: String = "" var bookUrl: String = ""
@@ -63,6 +78,41 @@ class TocViewModel(application: Application) : BaseViewModel(application) {
bookMarkCallBack?.upBookmark(newText) bookMarkCallBack?.upBookmark(newText)
} }
@Suppress("BlockingMethodInNonBlockingContext")
fun saveBookmark(treeUri: Uri) {
execute {
val book = bookData.value
?: 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()
)
}"
)
FileOutputStream(file).use {
GSON.writeToOutputStream(it, bookmark)
}
}
}.onError {
AppLog.put("导出失败\n${it.localizedMessage}", it, true)
}.onSuccess {
context.toastOnUi("导出成功")
}
}
interface ChapterListCallBack { interface ChapterListCallBack {
fun upChapterList(searchKey: String?) fun upChapterList(searchKey: String?)
@@ -50,8 +50,7 @@ object StringUtils {
* 将日期转换成昨天、今天、明天 * 将日期转换成昨天、今天、明天
*/ */
fun dateConvert(source: String, pattern: String): String { fun dateConvert(source: String, pattern: String): String {
@SuppressLint("SimpleDateFormat") val format = SimpleDateFormat(pattern, Locale.getDefault())
val format = SimpleDateFormat(pattern)
val calendar = Calendar.getInstance() val calendar = Calendar.getInstance()
kotlin.runCatching { kotlin.runCatching {
val date = format.parse(source) ?: return "" val date = format.parse(source) ?: return ""
+27 -10
View File
@@ -21,22 +21,39 @@
<item <item
android:id="@+id/menu_split_long_chapter" android:id="@+id/menu_split_long_chapter"
android:title="@string/split_long_chapter"
android:checkable="true" android:checkable="true"
android:title="@string/split_long_chapter"
app:showAsAction="never" /> app:showAsAction="never" />
</group> </group>
<item <group
android:id="@+id/menu_reverse_toc" android:id="@+id/menu_group_toc"
android:title="@string/reverse_toc" android:visible="true">
app:showAsAction="never" />
<item <item
android:id="@+id/menu_use_replace" android:id="@+id/menu_reverse_toc"
android:checkable="true" android:title="@string/reverse_toc"
android:title="@string/use_replace" app:showAsAction="never" />
app:showAsAction="never" />
<item
android:id="@+id/menu_use_replace"
android:checkable="true"
android:title="@string/use_replace"
app:showAsAction="never" />
</group>
<group
android:id="@+id/menu_group_bookmark"
android:visible="false">
<item
android:id="@+id/menu_export_bookmark"
android:title="@string/export"
app:showAsAction="never" />
</group>
<item <item
android:id="@+id/menu_log" android:id="@+id/menu_log"