diff --git a/app/src/main/java/io/legado/app/constant/AppPattern.kt b/app/src/main/java/io/legado/app/constant/AppPattern.kt index 2faf70daf..19fa46a41 100644 --- a/app/src/main/java/io/legado/app/constant/AppPattern.kt +++ b/app/src/main/java/io/legado/app/constant/AppPattern.kt @@ -12,5 +12,5 @@ object AppPattern { val nameRegex = Regex("\\s+作\\s*者.*") val authorRegex = Regex(".*?作\\s*?者[::]") val fileNameRegex = Regex("[\\\\/:*?\"<>|.]") - val splitGroupRegex = Regex("[,;]") + val splitGroupRegex = Regex("[,;,;]") } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt b/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt index 0c0b8e49a..e7ffc7fe0 100644 --- a/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt +++ b/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt @@ -11,7 +11,7 @@ interface BookSourceDao { @Query("select * from book_sources order by customOrder asc") fun liveDataAll(): LiveData> - @Query("select * from book_sources where bookSourceName like :searchKey or bookSourceGroup like :searchKey or bookSourceUrl like :searchKey order by customOrder asc") + @Query("select * from book_sources where bookSourceName like :searchKey or bookSourceGroup like :searchKey or bookSourceUrl like :searchKey or bookSourceComment like :searchKey order by customOrder asc") fun liveDataSearch(searchKey: String = ""): LiveData> @Query("select * from book_sources where enabled = 1 order by customOrder asc") diff --git a/app/src/main/java/io/legado/app/data/entities/BookSource.kt b/app/src/main/java/io/legado/app/data/entities/BookSource.kt index 3af66f972..29ffdcfd1 100644 --- a/app/src/main/java/io/legado/app/data/entities/BookSource.kt +++ b/app/src/main/java/io/legado/app/data/entities/BookSource.kt @@ -135,7 +135,7 @@ data class BookSource( bindings["java"] = this return AppConst.SCRIPT_ENGINE.eval(jsStr, bindings) } - + fun equal(source: BookSource) = equal(bookSourceName, source.bookSourceName) && equal(bookSourceUrl, source.bookSourceUrl) @@ -156,7 +156,7 @@ data class BookSource( && getContentRule() == source.getContentRule() private fun equal(a: String?, b: String?) = a == b || (a.isNullOrEmpty() && b.isNullOrEmpty()) - + data class ExploreKind( var title: String, var url: String? = null diff --git a/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt index 27ed39d84..bf1eed674 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt @@ -63,6 +63,9 @@ class BookSourceEditActivity : override fun onCompatOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.menu_save -> getSource().let { source -> + if (!source.equal(viewModel.bookSource ?: BookSource())){ + source.lastUpdateTime = System.currentTimeMillis() + } if (checkSource(source)) { viewModel.save(source) { setResult(Activity.RESULT_OK); finish() } } @@ -170,10 +173,11 @@ class BookSourceEditActivity : add(EditEntity("bookSourceUrl", source?.bookSourceUrl, R.string.source_url)) add(EditEntity("bookSourceName", source?.bookSourceName, R.string.source_name)) add(EditEntity("bookSourceGroup", source?.bookSourceGroup, R.string.source_group)) + add(EditEntity("bookSourceComment", source?.bookSourceComment, R.string.comment)) add(EditEntity("loginUrl", source?.loginUrl, R.string.login_url)) add(EditEntity("bookUrlPattern", source?.bookUrlPattern, R.string.book_url_pattern)) add(EditEntity("header", source?.header, R.string.source_http_header)) - add(EditEntity("bookSourceComment", source?.bookSourceComment, R.string.comment)) + } //搜索 val sr = source?.getSearchRule() diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt index a7d58dba5..59422c186 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt @@ -2,6 +2,7 @@ package io.legado.app.ui.book.source.manage import android.annotation.SuppressLint import android.app.Activity +import android.content.ActivityNotFoundException import android.content.Intent import android.os.Bundle import android.view.Menu @@ -9,18 +10,23 @@ import android.view.MenuItem import android.view.SubMenu import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.SearchView +import androidx.core.content.FileProvider import androidx.documentfile.provider.DocumentFile import androidx.lifecycle.LiveData import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import io.legado.app.App +import io.legado.app.BuildConfig import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.AppPattern import io.legado.app.data.entities.BookSource import io.legado.app.help.IntentDataHelp import io.legado.app.lib.dialogs.* +import io.legado.app.lib.dialogs.alert +import io.legado.app.lib.dialogs.noButton +import io.legado.app.lib.dialogs.okButton import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.primaryTextColor import io.legado.app.service.help.CheckSource @@ -41,6 +47,7 @@ import kotlinx.android.synthetic.main.view_search.* import org.jetbrains.anko.startActivity import org.jetbrains.anko.startActivityForResult import org.jetbrains.anko.toast + import java.io.File import java.text.Collator @@ -60,6 +67,7 @@ class BookSourceActivity : VMBaseActivity(R.layout.activity private var groups = linkedSetOf() private var groupMenu: SubMenu? = null private var sort = 0 + private var sortAscending = 0 override fun onActivityCreated(savedInstanceState: Bundle?) { initRecyclerView() @@ -86,6 +94,21 @@ class BookSourceActivity : VMBaseActivity(R.layout.activity when (item.itemId) { R.id.menu_add_book_source -> startActivity() R.id.menu_import_source_qr -> startActivityForResult(qrRequestCode) + R.id.menu_share_source -> { + try { + val json = GSON.toJson(adapter.getSelection()) + val intent = Intent(Intent.ACTION_SEND) + val file = FileUtils.createFileWithReplace("$filesDir/shareBookSource.json") + file.writeText(json) + val fileUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileProvider", file) + intent.type = "text/*" + intent.putExtra(Intent.EXTRA_STREAM, fileUri) + intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION + startActivity(Intent.createChooser(intent, getString(R.string.share_selected_source))) + } catch (e: ActivityNotFoundException) { + e.printStackTrace() + } + } R.id.menu_group_manage -> GroupManageDialog().show(supportFragmentManager, "groupManage") R.id.menu_import_source_local -> FilePicker @@ -93,22 +116,27 @@ class BookSourceActivity : VMBaseActivity(R.layout.activity R.id.menu_import_source_onLine -> showImportDialog() R.id.menu_sort_manual -> { item.isChecked = true - sort = 0 + sortCheck(0) initLiveDataBookSource(search_view.query?.toString()) } R.id.menu_sort_auto -> { item.isChecked = true - sort = 2 + sortCheck(1) initLiveDataBookSource(search_view.query?.toString()) } R.id.menu_sort_pin_yin -> { item.isChecked = true - sort = 3 + sortCheck(2) initLiveDataBookSource(search_view.query?.toString()) } R.id.menu_sort_url -> { item.isChecked = true - sort = 4 + sortCheck(3) + initLiveDataBookSource(search_view.query?.toString()) + } + R.id.menu_sort_time -> { + item.isChecked = true + sortCheck(4) initLiveDataBookSource(search_view.query?.toString()) } R.id.menu_enabled_group -> { @@ -168,18 +196,38 @@ class BookSourceActivity : VMBaseActivity(R.layout.activity } } bookSourceLiveDate?.observe(this, { data -> - val sourceList = when (sort) { - 1 -> data.sortedBy { it.weight } - 2 -> data.sortedBy { it.bookSourceName } - 3 -> data.sortedBy { it.bookSourceUrl } - else -> data + val sourceList = when (sortAscending % 2){ + 0 -> when (sort) { + 1 -> data.sortedBy { it.weight } + 2 -> data.sortedBy { it.bookSourceName } + 3 -> data.sortedBy { it.bookSourceUrl } + 4 -> data.sortedByDescending { it.lastUpdateTime} + else -> data + } + else -> when (sort) { + 1 -> data.sortedByDescending { it.weight } + 2 -> data.sortedByDescending { it.bookSourceName } + 3 -> data.sortedByDescending { it.bookSourceUrl } + 4 -> data.sortedBy { it.lastUpdateTime} + else -> data.reversed() + } } + recycler_view.scrollToPosition(0) val diffResult = DiffUtil .calculateDiff(DiffCallBack(ArrayList(adapter.getItems()), sourceList)) adapter.setItems(sourceList, diffResult) upCountView() }) } + private fun sortCheck (sortId: Int){ + if (sort == sortId){ + sortAscending +=1 + } + else{ + sortAscending = 0 + sort = sortId + } + } private fun initLiveDataGroup() { App.db.bookSourceDao().liveGroup().observe(this, { @@ -226,12 +274,12 @@ class BookSourceActivity : VMBaseActivity(R.layout.activity R.id.menu_disable_selection -> viewModel.disableSelection(adapter.getSelection()) R.id.menu_enable_explore -> viewModel.enableSelectExplore(adapter.getSelection()) R.id.menu_disable_explore -> viewModel.disableSelectExplore(adapter.getSelection()) - R.id.menu_export_selection -> FilePicker.selectFolder(this, exportRequestCode) R.id.menu_check_source -> checkSource() R.id.menu_top_sel -> viewModel.topSource(*adapter.getSelection().toTypedArray()) R.id.menu_bottom_sel -> viewModel.bottomSource(*adapter.getSelection().toTypedArray()) R.id.menu_add_group -> selectionAddToGroups() R.id.menu_remove_group -> selectionRemoveFromGroups() + R.id.menu_export_selection -> FilePicker.selectFolder(this, exportRequestCode) } return true } diff --git a/app/src/main/java/io/legado/app/utils/FileUtils.kt b/app/src/main/java/io/legado/app/utils/FileUtils.kt index eef940a86..ef67fab8b 100644 --- a/app/src/main/java/io/legado/app/utils/FileUtils.kt +++ b/app/src/main/java/io/legado/app/utils/FileUtils.kt @@ -55,6 +55,23 @@ object FileUtils { return file } + fun createFileWithReplace(filePath: String) : File{ + val file = File(filePath) + if (!file.exists()) { + //创建父类文件夹 + file.parent?.let { + createFolderIfNotExist(it) + } + //创建文件 + file.createNewFile() + } + else{ + file.delete() + file.createNewFile() + } + return file + } + fun getFile(root: File, vararg subDirFiles: String): File { val filePath = getPath(root, *subDirFiles) return File(filePath) diff --git a/app/src/main/res/drawable/ic_share.xml b/app/src/main/res/drawable/ic_share.xml index 0022d3b38..7b4b0103b 100644 --- a/app/src/main/res/drawable/ic_share.xml +++ b/app/src/main/res/drawable/ic_share.xml @@ -1,14 +1,9 @@ - - - - - \ No newline at end of file + + diff --git a/app/src/main/res/menu/book_source.xml b/app/src/main/res/menu/book_source.xml index 4ae595bb7..ed20f9b16 100644 --- a/app/src/main/res/menu/book_source.xml +++ b/app/src/main/res/menu/book_source.xml @@ -46,6 +46,10 @@ android:checkable="true" android:title="@string/sort_by_url" /> + @@ -92,4 +96,11 @@ android:title="@string/import_by_qr_code" app:showAsAction="never" /> + + + diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 0e6ae2b2d..9494414c8 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -759,5 +759,7 @@ 主题列表 使用保存主题,导入,分享主题 切換默認主題 + 分享選中書源 + 時間排序 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 7be3d0924..09d1225b4 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -759,6 +759,8 @@ 主题列表 使用保存主题,导入,分享主题 切換默認主題 + 分享選中書源 + 時間排序 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index fe359bf67..a32fa95bb 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -444,6 +444,7 @@ 请求头(header) 调试源 二维码导入 + 分享选中书源 扫描二维码 选中时点击可弹出菜单 主题 @@ -759,5 +760,6 @@ 主题列表 使用保存主题,导入,分享主题 切换默认主题 + 时间排序 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ccc85629a..6cdf21bb0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -388,6 +388,7 @@ 分类Url 登录URL(loginUrl) 源注释(sourceComment) + 请求头(header) 搜索地址(url) 发现地址规则(url) 书籍列表规则(bookList) @@ -444,7 +445,7 @@ Data parsing failed - Source http header + Debug source Import from QR code Scan QR code @@ -761,5 +762,7 @@ Save night theme config Theme list Save, Import, Share theme + Share selected sources + Sort by update time \ No newline at end of file diff --git a/app/src/main/res/xml/file_paths.xml b/app/src/main/res/xml/file_paths.xml index cdcf27e1b..779108dbf 100644 --- a/app/src/main/res/xml/file_paths.xml +++ b/app/src/main/res/xml/file_paths.xml @@ -6,4 +6,19 @@ + + + + + \ No newline at end of file