Merge pull request #370 from h11128/h11128pull

书源排序,分享,注释优化
pull/374/head
kunfei 4 years ago committed by GitHub
commit 3b978193ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      app/src/main/java/io/legado/app/constant/AppPattern.kt
  2. 2
      app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt
  3. 4
      app/src/main/java/io/legado/app/data/entities/BookSource.kt
  4. 6
      app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt
  5. 68
      app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt
  6. 17
      app/src/main/java/io/legado/app/utils/FileUtils.kt
  7. 13
      app/src/main/res/drawable/ic_share.xml
  8. 11
      app/src/main/res/menu/book_source.xml
  9. 2
      app/src/main/res/values-zh-rHK/strings.xml
  10. 2
      app/src/main/res/values-zh-rTW/strings.xml
  11. 2
      app/src/main/res/values-zh/strings.xml
  12. 5
      app/src/main/res/values/strings.xml
  13. 15
      app/src/main/res/xml/file_paths.xml

@ -12,5 +12,5 @@ object AppPattern {
val nameRegex = Regex("\\s+作\\s*者.*")
val authorRegex = Regex(".*?作\\s*?者[::]")
val fileNameRegex = Regex("[\\\\/:*?\"<>|.]")
val splitGroupRegex = Regex("[,;]")
val splitGroupRegex = Regex("[,;,;]")
}

@ -11,7 +11,7 @@ interface BookSourceDao {
@Query("select * from book_sources order by customOrder asc")
fun liveDataAll(): LiveData<List<BookSource>>
@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<List<BookSource>>
@Query("select * from book_sources where enabled = 1 order by customOrder asc")

@ -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

@ -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()

@ -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<BookSourceViewModel>(R.layout.activity
private var groups = linkedSetOf<String>()
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<BookSourceViewModel>(R.layout.activity
when (item.itemId) {
R.id.menu_add_book_source -> startActivity<BookSourceEditActivity>()
R.id.menu_import_source_qr -> startActivityForResult<QrCodeActivity>(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<BookSourceViewModel>(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<BookSourceViewModel>(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<BookSourceViewModel>(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
}

@ -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)

@ -1,14 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFF"
android:pathData="M9.866,9.9c-1.158,0-2.1,0.941-2.1,2.1s0.941,2.1,2.1,2.1s2.1-0.941,2.1-2.1S11.024,9.9,9.866,9.9z M9.866,13.1c-0.606,0-1.1-0.493-1.1-1.1s0.493-1.1,1.1-1.1s1.1,0.493,1.1,1.1S10.473,13.1,9.866,13.1z" />
<path
android:fillColor="#FFFFFF"
android:pathData="M16.267,16c-0.37,0-0.716,0.091-1.029,0.241l-1.656-1.657c0.513-0.734,0.817-1.623,0.817-2.584 s-0.305-1.85-0.817-2.584l1.656-1.657C15.551,7.909,15.896,8,16.267,8c1.323,0,2.399-1.077,2.399-2.4S17.59,3.2,16.267,3.2 s-2.4,1.076-2.4,2.399c0,0.369,0.091,0.715,0.241,1.028L12.45,8.285c-0.733-0.513-1.622-0.818-2.584-0.818 c-2.5,0-4.533,2.033-4.533,4.533s2.033,4.533,4.533,4.533c0.962,0,1.851-0.306,2.584-0.818l1.657,1.657 c-0.15,0.313-0.241,0.659-0.241,1.028c0,1.323,1.077,2.399,2.4,2.399s2.399-1.076,2.399-2.399S17.59,16,16.267,16z M16.267,4.8 c0.44,0,0.8,0.359,0.8,0.8c0,0.441-0.359,0.801-0.8,0.801c-0.441,0-0.801-0.359-0.801-0.801C15.466,5.159,15.825,4.8,16.267,4.8z M9.866,14.934c-1.617,0-2.934-1.316-2.934-2.934s1.316-2.934,2.934-2.934s2.933,1.316,2.933,2.934S11.483,14.934,9.866,14.934z M16.267,19.2c-0.441,0-0.801-0.359-0.801-0.8c0-0.441,0.359-0.801,0.801-0.801c0.44,0,0.8,0.359,0.8,0.801 C17.066,18.841,16.707,19.2,16.267,19.2z" />
</vector>
<path
android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"
android:fillColor="#000000"/>
</vector>

@ -46,6 +46,10 @@
android:checkable="true"
android:title="@string/sort_by_url" />
<item
android:id="@+id/menu_sort_time"
android:checkable="true"
android:title="@string/sort_by_lastUppdateTime" />
</group>
</menu>
@ -92,4 +96,11 @@
android:title="@string/import_by_qr_code"
app:showAsAction="never" />
<item
android:id="@+id/menu_share_source"
android:icon="@drawable/ic_share"
android:title="@string/share_selected_source"
app:showAsAction="never" />
</menu>

@ -759,5 +759,7 @@
<string name="theme_list">主题列表</string>
<string name="theme_list_summary">使用保存主题,导入,分享主题</string>
<string name="select_theme">切換默認主題</string>
<string name="share_selected_source">分享選中書源</string>
<string name="sort_by_lastUppdateTime">時間排序</string>
</resources>

@ -759,6 +759,8 @@
<string name="theme_list">主题列表</string>
<string name="theme_list_summary">使用保存主题,导入,分享主题</string>
<string name="select_theme">切換默認主題</string>
<string name="share_selected_source">分享選中書源</string>
<string name="sort_by_lastUppdateTime">時間排序</string>
</resources>

@ -444,6 +444,7 @@
<string name="source_http_header">请求头(header)</string>
<string name="debug_source">调试源</string>
<string name="import_by_qr_code">二维码导入</string>
<string name="share_selected_source">分享选中书源</string>
<string name="scan_qr_code">扫描二维码</string>
<string name="click_on_selected_show_menu">选中时点击可弹出菜单</string>
<string name="theme">主题</string>
@ -759,5 +760,6 @@
<string name="theme_list">主题列表</string>
<string name="theme_list_summary">使用保存主题,导入,分享主题</string>
<string name="select_theme">切换默认主题</string>
<string name="sort_by_lastUppdateTime">时间排序</string>
</resources>

@ -388,6 +388,7 @@
<string name="sort_url">分类Url</string>
<string name="login_url">登录URL(loginUrl)</string>
<string name="comment">源注释(sourceComment)</string>
<string name="source_http_header">请求头(header)</string>
<string name="r_search_url">搜索地址(url)</string>
<string name="r_find_url">发现地址规则(url)</string>
<string name="r_book_list">书籍列表规则(bookList)</string>
@ -444,7 +445,7 @@
<string name="net_error_10003">Data parsing failed</string>
<!--error string end-->
<string name="source_http_header">Source http header</string>
<string name="debug_source">Debug source</string>
<string name="import_by_qr_code">Import from QR code</string>
<string name="scan_qr_code">Scan QR code</string>
@ -761,5 +762,7 @@
<string name="save_night_theme_summary">Save night theme config</string>
<string name="theme_list">Theme list</string>
<string name="theme_list_summary">Save, Import, Share theme</string>
<string name="share_selected_source">Share selected sources</string>
<string name="sort_by_lastUppdateTime">Sort by update time</string>
</resources>

@ -6,4 +6,19 @@
<external-path
name="external_storage_root"
path="." />
<files-path
name="share"
path="." />
<external-files-path
name="external_files"
path="." />
<cache-path
name="cache"
path="." />
<external-cache-path
name="external_cache"
path="." />
<files-path
name="files"
path="." />
</paths>
Loading…
Cancel
Save